为什么构造的委托类的Invoke方法是virtual的?

问题描述 投票:0回答:2

我在 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的角度看起来是可以的。但为什么?为什么不生成密封类,这样在运行时就不会出现虚拟方法查找惩罚?

c# .net delegates
2个回答
2
投票

这是鸭子般的嘎嘎打字。 类似的类型使 System.Int32(一种值类型)派生自 ValueType(一种引用类型)。 没有意义,在 C# 中是非法的,但实际上是这样的。 委托的 Invoke 方法的真正实现隐藏在 CLR 中,并且是用 C++ 编写的静态函数。

但是可以肯定的是,将其注释为 virtual 是有一定道理的,因为它的“行为”就像一个 virtual 方法。 实际执行的代码并不像非虚拟类方法那样固定。 更难推理出绑定到静态方法的委托的正确模型应该是什么。 静态的虚拟方法? 它只是一只虚拟的鸭子。

阅读 C 中使用的函数指针可以帮助您为委托获得更好的心智模型。 委托是一个带有响铃的函数指针,它也可以存储目标对象。 C# 缺乏用另一种方式表达这一点的语法。


1
投票
Eric Lippert

的关于 .NET 继承的有趣引用:

我偶尔会被问到“但是像 int 这样的值类型怎么能 32位内存,不多也不少,可能是继承自object? 一个 内存中的对象比 32 位大得多;它有一个同步 块和一个虚函数表以及里面的各种东西。” 显然很多人认为继承与继承有关 以及值在内存中的布局方式。但价值是如何布局的 内存是一个实现细节,而不是合同义务 继承关系!

.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

方法需要使用的相同虚拟查找表。

    

© www.soinside.com 2019 - 2024. All rights reserved.