gpt4 book ai didi

c# - 实例方法的 'this' 参数可以是无类型的(即 System.Object)吗?

转载 作者:太空狗 更新时间:2023-10-30 01:09:56 24 4
gpt4 key购买 nike

我正在使用 System.Reflection.EmitTypeBuilder 发出一堆带有实例方法的自定义 .NET 类。例如:

public class EmittedClass
{
public bool TryGetName(out string value)
{
...
}

public bool TryGetAge(out int value)
{
...
}
}

所有方法都遵循可以由通用委托(delegate)描述的相同签名:

public delegate bool TryGetter<T>(out T value);

当然,我希望能够在调用站点上明确指定目标实例,如下所示:

var instance = InstanceFactory.CreateInstance();
var tryGetName = InstanceFactory.CreateTryGetter<string>("Name");
string name;
if (tryGetName(instance, out name)) // Problem here.
{
...
}

为此,我需要将委托(delegate)变成所谓的开放委托(delegate):

public delegate bool TryGetter<T>(object instance, out T value);

由于我没有目标实例的编译时类型,我需要将其作为 System.Object 传递。但是,这会在运行时中断,因为实例方法期望它的“this”是声明类的类型。哎哟。

我目前使用的解决方案是创建一个中间 lambda 表达式,它接受输入对象,执行运行时转换为目标类型,然后继续调用目标方法。它有效,但我对在中间出现这种困惑感到不安。

问题是:我能否以某种方式更改我发出的方法,以便它们的 this 参数将接受任何 System.Object 并仍然保持我发出的代码可验证?

如果不是,我想我仍然可以通过将方法设为静态并在它们的主体中执行强制转换来避免中间 lambda。然而,理想情况下,我想完全避免转换,但我怀疑由于 CIL 验证和元数据加载的工作方式,这在托管世界中是站不住脚的。

只是想知道是否有更了解 CIL 的人可以就此主题给我建议。谢谢!

更新:我正在尝试解决的问题

类具有属性,这些属性通常由字段支持。如果期望所述类的实例一次只保持一个状态,这很好。对于状态,我指的是给定时间实例字段中值的组合。

我的业务需求是实现一种替代普通字段的存储方式,使单个类实例能够同时拥有多个状态。此要求的一个附带目标是尽可能提高内存和访问速度方面的效率。

我的方法背后的核心思想是使用 System.Reflection.Emit 创建业务类的镜像,并让业务类维护一组这样的实例,每个实例对应于给定的状态.业务类的 getter 和 setter 自然必须连接到状态实例上的适当方法。涉及的细节很多,但这是核心思想。

我希望解释有助于理解我问这个问题的原因。我很欣赏这对许多人来说似乎是过度设计,但其他不涉及 System.Reflection.Emit 的替代方案显然太慢且耗费资源。我不能那样。

最佳答案

您不需要在委托(delegate)签名中表示“this”类型。

这是给定的委托(delegate)定义,如下所示:

public delegate bool TryGetter<T>(out T value);

任何形式的变量:

TryGetter<T> x;

可以持有:

  1. 带有签名的 R 类型实例方法 bool Foo(out T value) ,连同类型 R 的对象实例。
  2. 带有签名的静态方法 static bool Foo(out T value)
  3. 带有签名的静态方法 static bool Foo(R object, out T value)给定类型 R 的对象实例。

第三种形式称为委托(delegate)柯里化(Currying),它允许带有 N+1 个参数的静态方法表现得好像它是带有 N 个参数的实例方法(但是只有第一个参数可以柯里化(Currying))。

所以,你想要的界面是:

var instance = InstanceFactory.CreateInstance();
var tryGetName = InstanceFactory.CreateTryGetter<string>(instance,"Name");

然后你可以这样做:tryGetName()返回值。

您可能希望使用案例 #3,您在其中生成了 DynamicMethod签名bool TryGetWhatEver(TheTypeOfInstance obj, out WhatEver x) , 然后创建一个 TryGetter<WhatEver> .


但是我仍然很好奇您为什么需要这样做。除非您动态生成应用程序的大块(如 Rails),否则这似乎过于复杂。

关于c# - 实例方法的 'this' 参数可以是无类型的(即 System.Object)吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5791259/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com