當然,由於擴展方法只是靜態方法的一種 特例,我們同樣可以像用調用一般靜態方法那樣來調用擴展方法:
SampleExtensions.ExFunc(s);
這會得到完全一樣 的結果。而且事實上,編譯器也正是將擴展方法的調用翻譯為了一般形式的靜態 方法調用,然後才進行進一步的編譯。
擴展方法不僅能擴展同一個程序 集中的類型,同時也能擴展不同程序集甚至是已經發布了的程序集中的類型。下 面我們就在SampleExtensions中再添加一個擴展方法,用來擴展.Net Framework 的內建類型String(這個例子摘錄自C# 3.0語言規范,版權歸微軟公司所有。) :
public static int ToInt32(this string s)
{
return Int32.Parse(s);
}
然後,我們就可以象下面這 樣方便地將一個字符串轉換為一個整型了:
string sval = "20";
Console.WriteLine("String ’20’ means integer: {0}.", sval.ToInt32());
嘗試運行這段 代碼,會得到如下結果:
String ’20’ means integer: 20.
簡單地浏覽一下.NET Framework的文檔就會發現, System.String類型中的確沒有定義ToInt32方法,這說明我們的擴展方法在.Net Framework內建類型上仍然有效。
2、擴展方法的導入和權限
前面 我們探討了如何在同一個程序集中定義和調用擴展方法,那麼如果一個擴展方法 是定義在其他程序集中,我們又如何享用這些擴展方法所帶來的功能呢?事實非 常簡單,C# 3.0語言規范中規定,當我們使用using語句導入一個名命名空間時 ,就會同時導入該命名空間中所有靜態類型中定義的所有匿名方法。
3、 重載抉擇問題
看了上面的介紹我們不難發現一個問題:如果一個類型中 的某個實例方法與擴展方法的簽名等價(這裡說“等價”是因為擴展 方法與調用形式一樣的實例方法相比,要多一個表示被擴展類型的參數,也就是 第一個有this修飾符的參數),那麼當在被擴展類型的對象上調用方法時,就會 產生沖突。我們將這種沖突稱為重載抉擇問題。C# 3.0語言規范擴展了重載抉擇 ,將對擴展方法的調用也納入到重載抉擇的范疇之內,並且規定擴展方法擁有最 低的優先級。也就是說,對於一組特性類型、特定順序的參數列表,只有當被擴 展類型中沒有得以匹配的方法時,才考慮從擴展方法中選擇一個最合適的方法進 行調用。
現在,我們為上面的SampleExtensions類再添加一個用於擴展 SampleClass類型的擴展方法Func:
public static void Func (this SampleClass s)
{
s.Val = -1;
Console.WriteLine ("Am I appearing?");
}
如果用調用實例方法 的語法調用這個擴展方法,則其調用形式與調用無參的實例方法Func完全一致。 再次編譯並運行原來的程序,輸出的結果並沒有改變,也就是說這個擴展方法根 本沒有被調用,實際被調用的方法是實例方法Func。當然,如果將這個擴展方法 作為普通的靜態方法進行調用是沒有問題的。
另外如果兩個靜態類中為 同一個類型定義了簽名一致的靜態方法,則最後定義的靜態方法具有較高的優先 級;而同一程序集中定義的靜態方法優先級高於用using語句從其他命名空間中 導入的擴展方法;最後,如果兩個命名空間中包含簽名一致的擴展方法,則最後 引入的命名空間中的擴展方法優先級較高。
示例代碼簡介和小結
本文的代碼包括一個解決方案”CSharp3Sample1“,其中包括4個項 目Ex01~Ex04,分別對應於第1~4小節中的示例。您可以文章開始處的連接下載源 代碼。如果需要運行某一個示例,請在Visual Studio 2005的Solution Explorer窗口中右擊對應的項目,並選擇”Set as Startup Project“菜單項;然後按Ctrl+F5鍵運行示例,這裡建議按Ctrl+F5而不是 只按F5鍵來運行示例,是因為這樣能夠在運行結束後暫停,方便觀察結果(由於 個人原因我不願意在代碼中加入類似Console.ReadLine這樣的代碼來暫停程序的 運行)。 另外請注意要運行這些代碼需要首先正確安裝Visual Studio 2005 Beta2和Linq PrevIEw。
本文通過一系列可以執行並能夠看到結果的簡單 代碼介紹了C# 3.0中基本的語言增強——具有隱式類型的對象和數組 聲明、對象和集合初始化器、匿名類型和擴展方法。與C# 2.0之於C# 1.x不同, C# 3.0的這些語言增強不僅僅是為了是語言變得更加強大和優雅,更重要的是為 了後面的Lambda表達式和查詢表達式奠定了實現基礎。