典型場景
經常開發 .NET 應用程式的人,相信多少都會建立一套自己專屬的類別庫,畢竟作為通用目的 .NET Framework 不可能滿足所有應用程式的需求。比如說,自己開發的類別庫可能也會提供字串工具類別、日期時間、檔案 I/O、資料處理等工具類別。就拿字串處理來說好了,.NET 的 String 類別沒有提供字串反轉的方法,如果我們要在自己的字串工具類別中提供這個方法,可能會這麼寫:程式列表 1:StringExtension 類別
1: public static class StringExtension
2: {
3: // 字串反轉
4: public static string Reverse(string s)
5: {
6: if (String.IsNullOrEmpty(s))
7: return "";
8: char[] charArray = new char[s.Length];
9: int len = s.Length - 1;
10: for (int i = 0; i <= len; i++)
11: {
12: charArray[i] = s[len - i];
13: }
14: return new string(charArray);
15: }
16: }
於是,我們在應用程式中便可以這麼寫:
程式列表 2:呼叫 StringExtension 類別的靜態方法
OK! 到這裡為止都是我們非常熟悉的寫法。接著進入正題:擴充方法。1: class Program
2: {
3: static void Main(string[] args)
4: {
5: string s = "123456789";
6: Console.WriteLine(StringExtension.Reverse(s));
7: }
8: }
改用擴充方法
試想一下,如果「程式列表 2」的第 6 行在處理字串反轉時可以這麼寫: 6: Console.WriteLine(s.Reverse());
如果你覺得這種寫法還不賴,接著就來看看 StringExtension 類別的 Reverse 方法要如何修改才能讓它(看起來)成為 String 類別的一份子。很簡單,只要將「程式列表 1」的第 4 行改成這樣就行了:
4: public static string Reverse(this string s)
可是,編譯器怎麼知道我要擴充的是 String 類別呢?答案是:編譯器會將關鍵字 this 後面接著的型別視為該方法所欲擴充的類別。
再舉一個例子。假設我們有一個處理日期時間的工具類別,其中有一個 ToRocDateString 方法,程式碼如下:
程式列表 3:DateTimeExt 類別
ToRocDateString 方法的用途是將傳入的 DateTime 物件格式化成中華民國年份的日期字串,它需要兩個參數,一個是 DateTime 物件,另一個是日期分隔字元。現在,如果要讓它成為 DateTime 類別的擴充方法,就只要在第 4 行的第一個參數前面加上 this:1: public static class DateTimeExt
2: {
3: // 將 DateTime 物件格式化成中華民國年份的日期字串.
4: public static string ToRocDateString(DateTime date, char separator)
5: {
6: int year = (date.Year - 1911);
7: return year.ToString() + separator + date.Month + separator + date.Day;
8: }
9: }
4: public static string ToRocDateString(this DateTime date, char separator)
在使用 ToRocDateString 擴充方法時,只需要傳入一個參數,像這樣:
Console.WriteLine(DateTime.Now.ToRocDate('/'));
你不用擔心呼叫擴充方法時會忘記要傳入哪些參數,Visual Studuo 的 IntelliSense 功能會提示你。結語
擴充方法並沒有增加 .NET runtime 的負擔,一切都是由編譯器幫我們搞定--編譯器會到程式引用的各個 namespaces 中搜尋符合條件的擴充方法。如果你用 ILDASM 或 Reflector 工具去看編譯出來的 IL code,你就會看到,呼叫擴充方法的程式碼其實還是編譯成靜態方法呼叫。雖然它很方便(想像一下如果你要擴充的是 System.Object 類別!),但還是要注意避免濫用,如果用得太多,可能就會發生擴充方法名稱衝突的情形。此外,對於不是使用 Visual Studio 來寫程式的人來說,那些擴充方法呼叫可能會讓他們挺傷腦筋的吧!
Happy coding :)
from : https://www.huanlintalk.com/2009/01/csharp-3-extension-methods.html