[英]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:
MethodDeclaration應在Class的祖先鏈(通過其Extends鏈到達)或Class的接口樹(通過其InterfaceImpl條目到達)中索引方法。
由MethodDeclaration索引的方法不得為最終方法(其Flags.Final必須為0)[ERROR]
因此,您嘗試覆蓋的特定方法一定不能密封,並且必須在祖先類上定義,但是不要求指定的特定方法是祖先鏈中該插槽最具體的覆蓋。
話雖這么說,這可能是“完全出乎意料的”,因為將來的版本可能會強加安全限制來執行此類操作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.