【发布时间】:2015-11-26 19:17:32
【问题描述】:
我有一个类的层次结构:
class C1 { virtual object M1(); }
class C2: C1 { override sealed object M1(); }
class C3: C2 {
// I want to override M1()
// CSC gives me an error, obviously
override object M1();
}
但似乎有办法。在 IL 中,您可以覆盖具有不同名称的方法。因此,我们更改名称(M1_2() 覆盖 M1()),说它覆盖基类上的方法(C1::M1()),a la 显式接口实现,以及“最终”中间 (C2) 类不再重要了。
.class public auto ansi beforefieldinit N.C3
extends N.C2
{
.method private hidebysig virtual final
instance object M1_2() cil managed
{
.override N.C1::M1
ILasm 会很高兴地组装它,它在 ILSpy 中显示为
public class C3 : C2
{
object C1.M1_2()
然后在同一个类中,您可以定义一个调用this.M1_2() 的new M1。
所以你有 1) 被覆盖的 M1 (使用不同的名称,但仍然......)和 2)在 C3 中有一个 M1 方法(它是一个“桥”,但它就是你所看到的)。
但它看起来......错了。还是合法的?
如果你打电话
C1 obj = new C3();
obj.M1();
然后M1_2 被正确调用(我在调试器中验证了它)。似乎 CLR 仅在链是直接的 (C1::M1 > C2::M1 > C3::M1) 而不是在您“跳过”层次结构 (C1::M1 > C3::M1_2) 时才强制执行 final 约束。但是,您必须选择不同的名称。如果您使用相同的名称(M1):
.class public auto ansi beforefieldinit N.C3
extends N.C2
{
.method private hidebysig virtual final
instance object M1() cil managed
{
.override N.C1::M1
不行,扔System.TypeLoadException
附加信息:方法实现中引用的声明不能是最终方法 这是完全可以预料的。
我想知道:是那些 CLR 规则,还是我只是在实现中发现了一个极端情况? (规则中的一个极端情况会很好,在实施中......你不能指望它;))
【问题讨论】:
-
是什么让你尝试了这些东西并因此找到了这个? :)
-
StackOverflow 上已经询问并回答了所有简单的问题,所以......我必须找到并提出新的问题! :) 开个玩笑,我正在为此 github.com/dotnet/roslyn/issues/357 做一些研究,我不想最终找到一个可行的解决方案,但只能靠运气。
-
你测试Peverify.exe了吗?
-
是的...
All Classes and Methods in Project3.dll Verified.
标签: c# overriding clr cil