Overrides the final (IL) / sealed (C #) method with a different legal name?

I have a class hierarchy:

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(); } 

But there seems to be a way. In IL, you can override a method with a different name. Thus, we change the name ( M1_2() overrides M1() ), say, overrides the method in the base class ( C1::M1() ), the implementation of the explicit Java interface and the โ€œfinalโ€ on the intermediate ( C2 ) class no longer matter .

 .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 will happily collect it, and it shows in ILSpy how

 public class C3 : C2 { object C1.M1_2() 

Then in the same class you can define new M1 that calls this.M1_2() . So you have 1) an overridden M1 (with a different name, but still ...) and 2) there is an M1 method in C3 (this is a "bridge", but this is what you see).

But it looks ... wrong. Or is it something legal?

If you call

 C1 obj = new C3(); obj.M1(); 

then M1_2 is called correctly (I checked it in the debugger). It seems that the CLR applies the final constraint only if the chain is straight ( C1::M1 > C2::M1 > C3::M1 ), and not if you are "jumping" through the hierarchy ( C1::M1 > C3::M1_2 ). You must choose a different name. If you use the same name (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 

will not work throwing a System.TypeLoadException

Additional information: The declaration mentioned in the implementation of the method cannot be the final method. What is quite expected.

I wonder: are these CLR rules, or did I just find the cornerstone case in the implementation? (The corner case in the rules will be in order, in the implementation .. you cannot count on it;))

+2
source share
1 answer

It looks like an edge case in the specification.

In ECMA-335, section II of section 22.27 of MethodImpl:

  1. The Declaration method must index the method in the class ancestor chain (reached through the Extends chain) or in the class interface tree (reached through its InterfaceImpl record) [ERROR]

  2. A method indexed by MethodDeclaration is not final (its .Final flags must be 0) [ERROR]

Thus, the specific method that you are trying to override should not be sealed and must be defined in the ancestor class, but there is no requirement that the specified specific method be the most specific override for this slot in your ancestor chain.

Having said that, it is probably "rather unexpected" that future versions may impose security restrictions on this kind of thing.

+4
source

All Articles