2012-08-24 34 views
11

我有基類A爲什麼重載方法具有較低的優先級比實例方法

public class A 
{ 
    public virtual void Method(A parameter) 
    { 
     Console.WriteLine(MethodBase.GetCurrentMethod()); 
    } 
    public virtual void Method(B parameter) 
    { 
     Console.WriteLine(MethodBase.GetCurrentMethod()); 
    } 
} 

Inhereted B

public class B : A 
{ 
    public virtual void Method(object parameter) 
    { 
     Console.WriteLine(MethodBase.GetCurrentMethod()); 
    } 

    public override void Method(A parameter) 
    { 
     Console.WriteLine(MethodBase.GetCurrentMethod()); 
    } 

    public override void Method(B parameter) 
    { 
     Console.WriteLine(MethodBase.GetCurrentMethod()); 
    } 
} 

靜態類S與擴展方法

public static class S 
{ 
    public static void Method(this B instance, B parameter) 
    { 
     Console.WriteLine(MethodBase.GetCurrentMethod()); 
    } 
} 

實施例我們創建實例類型B並調用Method就可以了,我們預計它會是public override void Method(B parameter)實際結果是public virtual void Method(object parameter)

var b = new B(); 
b.Method(new B()); // B.Method (Object parameter) Why??? 

爲什麼編譯器不選擇更適合的方法? UPD爲什麼它不是擴展方法?

+3

'B'不是嵌套的,而是繼承的。 –

+0

@Henk Holterman謝謝 – user854301

+0

如果對象有相同名稱的方法,則不調用擴展方法。這是爲了避免破壞舊代碼,期望是調用舊方法而不是新擴展。 – Ankush

回答

10

爲什麼編譯器不會選擇更適合的方法?

因爲它是繼語言規範,如果任何候選方法最初在一個基類(超過,如果他們在派生類要覆蓋)宣佈的規則被忽略發現的候選方法時,除非派生類沒有任何適用的方法,在這一點上搜索移動到基類,等等。

這是designed to avoid the "brittle base class" problem,但我發現很難吞下面對的派生方法被覆蓋類。

的C#4規範的相關比特是7.4,它與此端:

對於比類型參數和接口,以及構件查找其它類型的構件查找在接口是嚴格的單繼承(繼承鏈中的每個接口只有零個或一個直接基接口),查找規則的作用就是派生成員隱藏具有相同名稱或簽名的基礎成員。

編輯:關於擴展方法...

,爲什麼它是不是擴展方法?

從規範的章節7.6.5.2:

在的一種形式的方法調用(第7.5.5.1節)

expr . identifier () 
expr . identifier (args) 
expr . identifier <typeargs> () 
expr . identifier <typeargs> (args) 

如果調用的正常處理髮現沒有適用的方法,試圖將該結構作爲擴展方法調用來處理

因此,基本上,擴展方法是只有作爲最後的手段使用。

+0

我認爲問題是爲什麼代碼調用繼承的方法,而不是擴展方法,但很難說? – podiluska

+0

@podiluska:我認爲擴展方法是一個紅色的鯡魚。該OP似乎並不期望它被稱爲... –

+0

它也很有趣,爲什麼擴展方法也不叫。 – user854301

相關問題