我在 CLR via C# 和代码项目文章 Delegate Behind the Scenes 中看到,当 C# 编译器看到此内容时
public delegate void MyDelegate(int intValue);
它实际上会生成类似这样的东西
class MyDelegate : System.MulticastDelegate
{
public virtual void Invoke(Int32 intValue);
...
}
问题是,为什么Invoke方法是virtual?这个生成的委托类型可以继承吗?从CLR的角度看起来是可以的。但为什么?为什么不生成密封类,这样在运行时就不会出现虚拟方法查找惩罚?
这是鸭子般的嘎嘎打字。 类似的类型使 System.Int32(一种值类型)派生自 ValueType(一种引用类型)。 没有意义,在 C# 中是非法的,但实际上是这样的。 委托的 Invoke 方法的真正实现隐藏在 CLR 中,并且是用 C++ 编写的静态函数。
但是可以肯定的是,将其注释为 virtual 是有一定道理的,因为它的“行为”就像一个 virtual 方法。 实际执行的代码并不像非虚拟类方法那样固定。 更难推理出绑定到静态方法的委托的正确模型应该是什么。 静态的虚拟方法? 它只是一只虚拟的鸭子。
阅读 C 中使用的函数指针可以帮助您为委托获得更好的心智模型。 委托是一个带有响铃的函数指针,它也可以存储目标对象。 C# 缺乏用另一种方式表达这一点的语法。
.NET 中有许多“特殊”继承类型:
System.ValueType
、
System.Enum
、System.Void
和 System.Delegate
,以及我确信的其他类型。使用 Reflector.NET 查看
System.Delegate
的内部结构,我可以看到许多这样的调用:
[MethodImpl(MethodImplOptions.InternalCall), SecurityCritical]
internal static extern MulticastDelegate InternalAlloc(RuntimeType type);
我怀疑我们正在处理不同的实现细节,它不需要委托使用
virtual
方法需要使用的相同虚拟查找表。