C#3.0新特性:擴展方法初探

字號:

C#3.0中一個激動人心的特性就是擴展方法:你可以使用實例方法的語法來調(diào)用靜態(tài)方法。本文仔細闡述了這一新特性并且給出了幾個相應(yīng)的例子。
    聲明擴展方法
    擴展方法的行為和靜態(tài)方法是非常類似的,你只能在靜態(tài)類中聲明它們。為聲明一個擴展方法,你需要給該方法的第一個參數(shù)指定this關(guān)鍵字,如下例:
    // Program.cs
    public static class EMClass
    {
    public static int ToInt32Ext(this string s)
    {
    return Int32.Parse(s);
    }
    public static int ToInt32Static(string s)
    {
    return Int32.Parse(s);
    }
    }
    class Program
    {
    static void Main(string[] args)
    {
    string s = "9";
    int i = s.ToInt32Ext(); // LINE A
    Console.WriteLine(i);
    int j = EMClass.ToInt32Static(s); // LINE B
    Console.WriteLine(j);
    Console.ReadLine();
    }
    }
    為編譯如上代碼,你需要安裝Visual Studio 2005和LINQ的預(yù)覽版。如果你已經(jīng)安裝了VS2005,那么你將在Visual C#的LINQ Preview里看到三個新的工程模板:LINQ命令行應(yīng)用程序,LINQ窗口程序和LINQ庫。如下操作編譯代碼:
    1. 打開VS2005編輯器,創(chuàng)建一個新工程,在新建工程窗口中選擇LINQ Console作為工程模板。
    2. 將工程命名為ExtensionMethods,點擊Ok。
    3. 將如上代碼鍵入編輯器。
    4. 按下F5編譯工程并運行。
    如果你只是安裝了.net 2.0,那么你可以運行命令行編譯器:
    Csc.exe /reference:"C:\Program Files\LINQ Preview\Bin
    \System.Data.DLINQ.dll"
    /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll
    /reference:"C:\Program Files\LINQ Preview\Bin\System.Query.dll"
    /reference:"C:\Program Files\LINQ Preview\Bin\System.XML.XLINQ.dll"
    /target:exe Program.cs
    就像你在如上代碼里所看到的那樣,擴展方法(ToInt32Ext)和普通的靜態(tài)方法(ToInt32Static)的不同在于:
    1. 擴展方法的第一個參數(shù)有一個this關(guān)鍵字,而靜態(tài)方法不會在它的參數(shù)聲明里有this關(guān)鍵字。
    2. 當使用擴展方法的是哦戶,使用this關(guān)鍵字聲明的的參數(shù)沒有進行傳遞。在上面的例子里,Line A就是一個使用擴展方法ToInt32Ext的例子。不需要將參數(shù)傳遞給它。當靜態(tài)方法在使用的時候,是不能忽略掉任何的參數(shù)的。所有的參數(shù)必須傳遞進入函數(shù)。Line B就是一個例子。
    3. 擴展方法只能在靜態(tài)類中定義。對于靜態(tài)方法,這并不成為一個要求,因為靜態(tài)方法可以在一個靜態(tài)類或普通類中存在。
    4. 擴展方法只能針對實例調(diào)用。
    擴展方法,盡管本質(zhì)上還是靜態(tài)的,但是只能針對實例調(diào)用。如果在一個類中調(diào)用它們將會引發(fā)編譯錯誤。調(diào)用它們的類實例是由聲明中的第一個參數(shù)決定的,就是有關(guān)鍵字this修飾的那個。
    在IL內(nèi)部
    如果你觀看IL里對以上代碼的分析結(jié)果,你將會看到如下圖的結(jié)果:
    以下是IL對于擴展方法ToInt32Ext的分析:
    .method public hidebysig static int32 ToInt32Ext(string s) cil managed
    {
    .custom instance void [System.Query]System.Runtime
    .CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
    // Code size 12 (0xc)
    .maxstack 1
    .locals init ([0] int32 CSCODE_REPLACEMENT 200)
    IL_0000: nop
    IL_0001: ldarg.0
    IL_0002: call int32 [mscorlib]System.Int32::Parse(string)
    IL_0007: stloc.0
    IL_0008: br.s IL_000a
    IL_000a: ldloc.0
    IL_000b: ret
    } // end of method EMClass::ToInt32Ext
    以下代碼是IL對靜態(tài)方法ToInt32Static的分析:
    .method public hidebysig static int32 ToInt32Static(string s) cil managed
    {
    // Code size 12 (0xc)
    .maxstack 1
    .locals init ([0] int32 CSCODE_REPLACEMENT 300)
    IL_0000: nop
    IL_0001: ldarg.0
    IL_0002: call int32 [mscorlib]System.Int32::Parse(string)
    IL_0007: stloc.0
    IL_0008: br.s IL_000a
    IL_000a: ldloc.0
    IL_000b: ret
    } // end of method EMClass::ToInt32Static
    .custom instance void: 本行代碼說明本方法只能針對實例使用。
    [System.Query]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ):本行代碼說明擴展特性被使用了。