擴充方法使您能夠向現有類型“添加”方法,而無需建立新的衍生類別型、重新編譯或以其他方式修改原始類型。 擴充方法是一種特殊的靜態方法,但可以像擴充類型上的執行個體方法一樣進行調用。 對於用 C# 和 Visual Basic 編寫的用戶端代碼,調用擴充方法與調用在類型中實際定義的方法之間沒有明顯的差異。
最常見的擴充方法是 LINQ 標準查詢運算子,這些運算子在現有 System.Collections.IEnumerable 和 System.Collections.Generic.IEnumerable(Of T) 類型中添加了查詢功能。若要使用這些標準查詢運算子,請先使用 using System.Linq 指令將它們納入範圍中。 然後,任何實現了 IEnumerable(Of T) 的類型看起來都具有 GroupBy、OrderBy、Average 等執行個體方法。 在 IEnumerable(Of T) 類型的執行個體(如 List(Of T) 或 Array)後鍵入“dot”時,可以在 IntelliSense 陳述式完成中看到這些附加方法。
下面的樣本示範如何對一個整數數組調用標準查詢運算子 OrderBy方法。 括弧裡面的運算式是一個 lambda 運算式。 很多標準查詢運算子採用 lambda 運算式作為參數,但這不是擴充方法的必要條件。
擴充方法被定義為靜態方法,但它們是通過執行個體方法文法進行調用的。 它們的第一個參數指定該方法作用於哪個類型,並且該參數以 this修飾符為首碼。 僅當您使用 using 指令將命名空間顯式匯入到原始碼中之後,擴充方法才位於範圍中。
下面的樣本示範為 System.String類定義的一個擴充方法。 請注意,它是在非嵌套、非泛型靜態類內部定義的:
namespace ExtensionMethods{ public static class MyExtensions { public static int WordCount(this String str) { return str.Split(new char[] { ' ', '.', '?' }, StringSplitOptions.RemoveEmptyEntries).Length; } } }
可使用以下 using 指令將 WordCount 擴充方法放入範圍中:
using ExtensionMethods;
而且,可以在應用程式中使用以下文法對該擴充方法進行調用:
string s = "Hello Extension Methods";int i = s.WordCount();
在代碼中,可以使用執行個體方法文法調用該擴充方法。 但是,編譯器產生的中繼語言 (IL) 會將代碼轉換為對靜態方法的調用。 因此,並未真正違反封裝原則。 實際上,擴充方法無法訪問它們所擴充的類型中的私人變數。
在編譯時間綁定擴充方法
可以使用擴充方法來擴充類或介面,但不能重寫擴充方法。 與介面或類方法具有相同名稱和簽名的擴充方法永遠不會被調用。 編譯時間,擴充方法的優先順序總是比類型本身中定義的執行個體方法低。 換句話說,如果某個類型具有一個名為 Process(int i) 的方法,而您有一個具有相同簽名的擴充方法,則編譯器總是綁定到該執行個體方法。 當編譯器遇到方法調用時,它首先在該類型的執行個體方法中尋找匹配的方法。 如果未找到任何匹配方法,編譯器將搜尋為該類型定義的任何擴充方法,並且綁定到它找到的第一個擴充方法。 下面的樣本示範編譯器如何確定要綁定到哪個擴充方法或執行個體方法。