簡體   English   中英

覆蓋具有其他名稱的最終(IL)/密封(C#)方法合法嗎?

[英]Is overriding a final (IL) / sealed (C#) method with a different name legal?

我有一個類的層次結構:

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() )上的方法, 一個顯式接口實現以及中間層上的“最終”( 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()

然后在同一類中,可以定義一個new M1 ,它調用this.M1_2() 因此,您有1)覆蓋的M1 (具有不同的名稱,但仍然...)和2)在C3中具有M1方法(這是一個“橋梁”,但這就是您看到的)。

但是看起來...錯了。 還是合法的?

如果你打電話

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

然后正確調用了M1_2 (我在調試器中對其進行了驗證)。 似乎只有在鏈是直接的( C1::M1 > C2::M1 > C3::M1 )時,CLR才會強制執行final約束,而在層次結構上“跳轉”時( 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

將無法正常工作,引發System.TypeLoadException

附加信息:在方法實現中引用的聲明不能是完全期望的最終方法。

我想知道:是那些CLR規則,還是我只是在實施中發現了一個極端案例? (在實施中,規則中的一個極端案例是很好的。您不能指望它;))

在規范中看起來像是邊緣情況。

在ECMA-335中,分區II第22.27節MethodImpl:

  1. MethodDeclaration應在Class的祖先鏈(通過其Extends鏈到達)或Class的接口樹(通過其InterfaceImpl條目到達)中索引方法。

  2. 由MethodDeclaration索引的方法不得為最終方法(其Flags.Final必須為0)[ERROR]

因此,您嘗試覆蓋的特定方法一定不能密封,並且必須在祖先類上定義,但是不要求指定的特定方法是祖先鏈中該插槽最具體的覆蓋。

話雖這么說,這可能是“完全出乎意料的”,因為將來的版本可能會強加安全限制來執行此類操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM