在delegate
C# 中使用关键字时,C# 编译器会自动生成从 class 派生的System.MulticastDelegate
类。
这个编译器生成的类也包含 3 个方法:Invoke, BeginInvoke and EndInvoke
.
所有这三个方法都被标记public virtual extern
了,但有趣的是类本身也被标记了sealed
。
在密封类中定义的虚拟方法不仅违反直觉,而且在 C# 中实际上是非法的。
所以我的问题是,这是否有特定的原因,或者它只是记住一些假设的未来增强而做的那些无害的事情之一?
编辑1:
原因是否可以强制使用“callVirt”IL操作码而不是“call”,以便在尝试执行这三种方法中的任何一种之前,CLR总是检查委托对象是否为空?虽然我不明白为什么 adelegate
在这方面应该是一个特例。
强制使用也不是对性能的影响callvirt
(尽管它可能是微不足道的)
编辑2:
添加了 CIL 标记,事实证明,定义委托的 C# 方式实际上是由 CIL 标准规定的。标准规定(以下不是全文)
委托应具有 System.Delegate 的基本类型。代表应被声明为密封,并且代表应拥有的唯一成员是此处指定的前两个或全部四个方法。这些方法应在运行时声明和管理。它们不应有实体,因为该实体应由 VES 自动创建。委托上可用的其他方法继承自基类库中的 System.Delegate 类。委托方法是:
- 实例构造函数
- Invoke 方法应该是虚拟的
- BeginInvoke 方法(如果存在)应该是虚拟的
- EndInvoke 方法应该是虚拟的
所以这绝对不是编译器过程的副作用,或者类似于其他有趣的编译器输出。
如果标准强调某事,那一定是有充分理由和理由的。
那么现在的问题是,为什么 CIL 代表标准同时强调密封和虚拟?
问题在这里吗?:
它们不应有实体,因为该实体应由 VES 自动创建。
它们是否标记为虚拟,以便可以在调用这些方法时执行 VES/CLR 生成的主体?