Lor*_*tté 2 c# clr overriding cil
我有一个类的层次结构:
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();
}
Run Code Online (Sandbox Code Playgroud)
但似乎有一种方法.在IL中,您可以使用其他名称覆盖方法.所以,我们更改名称(M1_2()覆盖M1()),说它覆盖了基类(C1::M1())上的方法,一个显式接口实现,而中间(C2)类上的"final" 不再重要.
.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
Run Code Online (Sandbox Code Playgroud)
ILasm很乐意组装它,它在ILSpy中显示为
public class C3 : C2
{
object C1.M1_2()
Run Code Online (Sandbox Code Playgroud)
然后在同一个类中,您可以定义new M1哪些调用this.M1_2().所以你有1)被覆盖M1(使用不同的名称,但仍然......)和2)M1在C3中有一个方法(它是一个"桥",但它是你所看到的).
但它看起来......错了.还是合法的?
如果你打电话
C1 obj = new C3();
obj.M1();
Run Code Online (Sandbox Code Playgroud)
然后M1_2被正确调用(我在调试器中验证了它).似乎CLR final仅在链是direct(C1::M1 > C2::M1 > C3::M1)时强制执行约束,而不是在层次结构(C1::M1 > C3::M1_2)上"跳转"时强制执行约束.但是,您必须选择其他名称.如果您使用相同的名称(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
Run Code Online (Sandbox Code Playgroud)
不会工作,抛出一个 System.TypeLoadException
附加信息:方法实现中引用的声明不能是完全预期的最终方法.
我想知道:那些CLR规则,还是我刚刚在实现中发现了一个极端情况?(规则中的一个角落案例就可以了,在实施中......你不能指望它;))
看起来像规范中的边缘情况.
在ECMA-335中,Partition II第22.27节MethodImpl:
MethodDeclaration将索引类的祖先链中的方法(通过其Extends链到达)或类的接口树(通过其InterfaceImpl条目到达)[ERROR]
MethodDeclaration索引的方法不是final(Flags.Final应为0)[ERROR]
因此,您尝试覆盖的特定方法不得密封,并且必须在祖先类上定义,但不要求指定的特定方法是祖先链中该槽的最特定覆盖.
话虽如此,这可能是"足够意外",以至于未来版本可能会施加安全限制来执行此类操作.
| 归档时间: |
|
| 查看次数: |
276 次 |
| 最近记录: |