2011-07-01 113 views
5

擴展方法如何在內部實現?我的意思是當編譯器看到擴展方法的聲明時發生了什麼,以及在有對擴展方法的調用時在運行時發生了什麼。內部如何實現擴展方法

是否涉及反思?或者當你有一個擴展方法是它的代碼注入目標類類型元數據與一些額外的標誌注意到這是一個擴展方法,然後CLR知道如何處理?

所以一般情況下,引擎蓋下會發生什麼?

回答

6

正如其他同事所說的那樣,它只是一種靜態方法。 這完全是關於編譯器,我們可以說CLR甚至不知道擴展方法。 你可以嘗試檢查IL代碼..

下面是一個例子

static class ExtendedString 
{ 
    public static String TestMethod(this String str, String someParam) 
    { 
     return someParam; 
    } 
} 

static void Main(string[] args) 
{ 
    String str = String.Empty; 
    Console.WriteLine(str.TestMethod("Hello World!!")); 
    ........ 
} 

這裏是IL代碼。

IL_0001: ldsfld  string [mscorlib]System.String::Empty 
    IL_0006: stloc.0 
    IL_0007: ldloc.0 
    IL_0008: ldstr  "Hello World!!" 
    IL_000d: call  string StringPooling.ExtendedString::TestMethod(string, 
                     string) 
    IL_0012: call  void [mscorlib]System.Console::WriteLine(string) 
    IL_0017: nop 

正如你所看到的,它只是一個靜態方法的調用。 該方法未添加到類中,但編譯器使它看起來像這樣。 和反射層您可以看到的唯一區別就是CompilerServices。ExtensionAttribute被添加。

4

擴展方法轉換爲靜態函數。換句話說,它們是靜態函數的語法糖。

2

我不認爲reflection涉及擴展方法。擴展方法的處理方式與您在helper class中編寫static helper function的方式相同,唯一的區別是編譯器會爲您執行此操作。

1

要澄清上述答案...擴展方法是靜態函數。 .NET 3.5中的其他功能允許將它們解釋爲它們是所討論類型的新方法。

0

擴展方法非常像static方法,唯一的區別在於它有一個屬性CompilerServices.ExtensionAttribute,這有助於將其識別爲擴展方法。

可以read this

0

是,擴展方法只是靜態方法。他們對於他們認爲「延伸」的課程沒有額外的權限。但是,編譯器確實用ExtensionAttribute標記了「extension」靜態方法。你可以在IL中看到這個。這使得編譯器專門處理它,以便您不能將其作爲常規靜態方法調用。例如,這不會編譯:

var test = new [] { "Goodbye", "Cruel", "World" }; 
var result = IEnumerable<string>.Where<string>(test, s => s.Length > 5); 

即使這是發生了什麼。

但是正如下面的LukeH注意到的,你可以在實際定義的類上調用它......愚蠢的我。

+0

您可以直接調用擴展方法作爲靜態方法,它只是一個靜態方法在不同的靜態類上:var result = Enumerable.Where (test,s => s.Length> 5);' – LukeH

+0

'絕對正確。嘗試將其從「正在擴展」的類型中調用它是沒有意義的。我的錯。 – Einar