我在CLR via C#和codeproject文章Delegate Behind the Scenes中看到,当C#编译器看到这个
时public delegate void MyDelegate(int intValue);
它实际上会产生类似这样的东西
class MyDelegate : System.MulticastDelegate
{
public virtual void Invoke(Int32 intValue);
...
}
问题是,为什么Invoke方法是虚拟的?这个生成的委托类型可以继承吗?从CLR的角度来看,它可以。但为什么?为什么不生成密封类,因此在运行时不会有虚拟方法查找惩罚?
答案 0 :(得分:1)
这是一种类似于鸭子的庸医打字。类似的类型使System.Int32(一种值类型)派生自ValueType,一种引用类型。毫无意义,在C#中是非法的,但实际上就是这样。委托的Invoke方法的真正实现隐藏在CLR中,是一个用C ++编写的静态函数。
但是,确定,将其注释为虚拟有点意义,因为它的行为就像虚拟方法一样。执行的实际代码不像非虚拟类方法那样修复。更难理解的是,对于绑定到静态方法的委托,正确的模型应该是什么。一个静态的虚方法?
这只是一个虚拟的鸭子。
读取C中使用的函数指针可以帮助您为代理人获得更好的心理模型。委托是一个带有铃铛的函数指针,它也可以存储目标对象。 C#缺乏表达另一种方式的语法。
答案 1 :(得分:1)
这是Eric Lippert关于.NET中继承的有趣引用:
我偶尔会被问到“但是值类型怎么样,比如int,哪个是 32位内存,不多也不少,可能从对象继承?一个 在内存中布局的对象大于32位;它有一个同步 阻止和虚拟功能表以及那里的各种东西。“ 显然很多人都认为继承有一些事情可做 如何在内存中布置一个值。但是如何规划价值 记忆是一种实施细节,而不是合同义务 继承关系!
.NET中有许多“特殊”继承类型:System.ValueType
,System.Enum
,System.Void
和System.Delegate
,其中我肯定。< / p>
使用Reflector.NET查看System.Delegate
的内部结构,我可以看到许多这样的调用:
[MethodImpl(MethodImplOptions.InternalCall), SecurityCritical]
internal static extern MulticastDelegate InternalAlloc(RuntimeType type);
我怀疑我们正在处理不同的实现细节,不需要委托使用virtual
方法需要使用的相同虚拟查找表。