2011-04-06 52 views
1

我想知道C#中擴展方法的行爲。請看下面的例子:C#擴展方法不能按預期工作 - 請參閱示例

static string ExtendedToString(this object oObj) 
{ 
    return "Object"; 
} 

static string ExtendedToString(this Array oArray) 
{ 
    return "Array"; 
} 

// Example 1: int array - working as expected. 
int[] o = new int[] { 1, 2, 3 }; 
o.ExtendedToString(); // returns "Array" 

// Example 2: array as object - did not expect the result. 
object o = new int[] { 1, 2, 3 }; 
o.ExtendedToString(); // returns "Object" 

爲什麼(在最後一種情況)被稱爲對象的擴展方法,而不是1爲int []?

回答

9

重載分解離子是在編譯時執行的。編譯器發現o被聲明爲object,所以它調用了需要object的超載。 o實際上在運行時包含數組的事實是不相關的,因爲編譯器不知道它。

這實際上是不特定於擴展方法,你會通過調用它作爲一個正常的靜態方法(ExtensionsClass.ExtendedToString(o)

+0

有道理。這很奇怪,因爲它看起來像一個虛擬的方法,但它不是 - 這是令人困惑的部分。謝謝。 – Krumelur 2011-04-06 12:32:08

+0

@Krumelur,請記住,擴展方法只是語法糖來調用靜態方法 – 2011-04-06 12:34:27

+0

是的。這就是我的意思:在使用它們時它們看起來不像靜力學。 – Krumelur 2011-04-06 12:45:05

1

您聲明O作爲對象:

object o = new int[] { 1, 2, 3 }; 

這就是爲什麼:

o.ExtendedToString(); // returns "Object" 

,但你可以

int[] obj = o as int[]; 
obj.ExtendedToString(); // returns "Array" 

的分辨率取決於(靜態)類型

1

由於靜態類型的得到相同的結果。擴展方法由編譯器重新編譯,就像通過常規語法調用它們一樣。在編譯時,第二個對象o具有Object類型,所以對象的擴展方法被稱爲

0

Thomas Levesque已經完美地解釋了爲什麼你的代碼不起作用,所以我不會再重複。解決方法是在運行時用isas測試:

static string ExtendedToString(this object oObj) 
{ 
    if(oObj is Array) 
     return "Array"; 
    else 
     return "Object"; 
} 

以這樣的方式一般型式試驗是有點反模式的,你應該更喜歡虛擬方法在可能的情況。但在這種情況下,它可能仍然是最好的解決方案,因爲您無法更改Array/Object類。

如果有很多類需要特殊處理,您可以考慮Type - >Func<object,string>詞典。