gpt4 book ai didi

c# - 在值类型上定义的扩展方法不能用于创建委托(delegate)——为什么不呢?

转载 作者:IT王子 更新时间:2023-10-29 04:11:31 25 4
gpt4 key购买 nike

可以将扩展方法分配给与其在对象上的用法相匹配的委托(delegate),如下所示:

static class FunnyExtension {
public static string Double(this string str) { return str + str; }
public static int Double(this int num) { return num + num; }
}


Func<string> aaMaker = "a".Double;
Func<string, string> doubler = FunnyExtension.Double;

Console.WriteLine(aaMaker()); //Prints "aa"
Console.WriteLine(doubler("b")); //Prints "bb"

如果他们扩展的类型是值类型,它将不起作用:

Func<int> eightMaker = 4.Double;    //Error CS1113: Extension methods 'FunnyExtension.Double(int)' defined on value type 'int' cannot be used to create delegates
Func<int, int> intDoubler = FunnyExtension.Double; //Works

这给出了

Error CS1113: Extension methods 'FunnyExtension.Double(int)' defined on value type 'int' cannot be used to create delegates.

为什么他们不能?

最佳答案

在回应我的另一个回答时,Eric Smith 正确地指出:

"... because it would require implicitly boxing the receiver type parameter ...". Which is what happens anyway, if you do something like this: Func f = 5.ToString; Which is perfectly legal.

思考这个问题让我有了一个新的答案。试试这个尺寸:

结构上的普通“实例”方法在 CIL 级别采用“托管指针”(类型 &)作为接收器参数。这是必要的,以便结构上的实例方法可以分配给结构的字段。参见 Partition II, Section 13.3 .

类似地,类的实例方法采用“对象引用”(O 类型)作为接收者参数(区别在于这是指向托管堆的指针,需要跟踪GC)。

由于 CIL &O 都可以(并且已经)由指针实现,因此对于委托(delegate)实现来说,一切都很简单。无论委托(delegate)是捕获静态方法、类实例方法还是结构实例方法,它需要做的就是将指向其 _target 的指针传递给函数的第一个参数。

但我们正在讨论的场景破坏了这一点。将 int 作为第一个参数的静态扩展方法需要 int32 类型的 CIL 参数(参见第 III 部分,第 1.1.1 节)。 这就是事情偏离正轨的地方。我看不出有任何理由不可能委托(delegate)的实现意识到这正在发生(因为例如,通过检查与正在捕获的 MethodInfo 相关联的元数据)并发出一个 thunk,该 thunk 将拆箱 _target 并将其作为第一个参数传递,但是委托(delegate)给经典不需要这结构上的实例方法,因为它们无论如何都希望有一个指针并且不会出现(根据我之前错误答案中的示例判断)被实现。显然,所讨论的特定值类型将控制所需 thunk 的确切性质。

除非我遗漏了一个更基本的实现障碍(我可以想象它会给验证者带来问题,例如),似乎可以合理地扩展运行时来支持这种情况,但所有迹象表明这是运行时的限制,而不是 C# 编译器本身的限制。

关于c# - 在值类型上定义的扩展方法不能用于创建委托(delegate)——为什么不呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1016033/

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