今天的話題,我們來聊下擴展方法,自己也真心感歎自己的文筆,那叫一個慘啊,回顧寫的文章,看著看著也忘記當時是懷著什麼心態寫的,哈哈,現代人真心是太隨性了,可能也是太冷漠了,接著寫的吧,總是會有幫助,也會有收獲的。
擴展方法是從C#3開始出現在我們的眼前,它即有靜態方法的優點,也使我們的代碼更具可讀性,可以像實例方法一樣調用靜態方法。在擴展方法沒有出現前,我們在代碼中常常出現靜態的工具類(當然,即使現在我們來會使用靜態工具類,那都是前人的智慧結晶),如一個字符串幫助類、時間轉換工具類。想像一下,當我們得到一個封裝好的類庫,裡面的源代碼是不可見,我們只是類庫的使用者,但類庫的開發者也不是十全十美的思路,總是會有一些遺漏。我們拿簡單的來說,比如現在我拿到一份代碼,代碼中有一個Room類,如下:
1 class Room 2 { 3 public string Name { get; set; } 4 }
上面的代碼是不能修改的,想象一個我們可以使用什麼方法給對象的Name屬性賦值?我們可以使用實例一個Room對象,直接賦值,但現在我想給Room類加一個SetName的方法,那擴展方法會幫助到我們。如:
1 static class RoomExt 2 { 3 public static void SetName(this Room room, string name) 4 { 5 room.Name = name; 6 } 7 } 8 9 Room room = new Room(); 10 room.Name = "草堂"; 11 Console.WriteLine(room.Name); 12 room.SetName("澡堂"); 13 Console.WriteLine(room.Name); 14 Console.ReadKey();
上述代碼中,SetName方法就是Room類的擴展方法,可以像調用實例方法一樣調用它。Room類的開發者忘記給Room類增加一個SetName方法,那我們就使用擴展方法給Room類加一個方法,調用的方式和實例方法一樣。SetName的第一個參數為擴展類型,指定要擴展的類,並使用關鍵字this,規定而已,請遵守之。方法的修飾符為static,呵呵,遵守之。如果我們寫的代碼是外部調用的話,請使用public關鍵字,使用pirvate關鍵字,那就只能在為其擴展的擴展方法中才能使用。
1 room.SetName("澡堂"); //調用SetName方法,內部會實現為RoomExt.setName(room,"澡堂")
上面的代碼是不是和我們的靜態工具一樣,是的,使用擴展方法,可以使用代碼更具可讀性。當然上述的代碼只是一個簡單使用,在我們正常使用中,自己寫的類肯定會加入合適的實例方法,即使是類庫的,那也會讓類庫開發者加一個方法。但如果是微軟的開發者沒給出合適的方法,沒辦法,自己加吧。所以擴展方法經常被我們用來擴展系統類型的方法。擴展方法類似靜態方法,但它也必須要具有以下的特征:
找到合適的方法
當我們使用SetName時,會先在實例方法中找,是否有這個方法,如果沒有,會從引入的命名空間中找簽名符合的方法,也有可能全有重載情況發生,那基於"誰更優"找到方法並執行。
對空類型進行擴展
實際上是對object對象進行擴展,如
1 static class objectExt 2 { 3 public static bool IsNull(this object o) 4 { 5 return o == null; 6 } 7 }
使用如下:
1 static class objectExt 2 { 3 public static bool IsNull(this object o) 4 { 5 return o == null; 6 } 7 } 8 9 10 Room room1 = null; 11 Console.WriteLine(room1.IsNull());
使用是不是很生動,如果你願意也可以在類中加一個實例方法IsNull,或者使用靜態工具來判斷一個實例是否為null。實例方法我擴展方法是可以重載的,如
1 class Room 2 { 3 public string Name { get; set; } 4 5 public bool IsNull() 6 { 7 return this == null; 8 } 9 }
在Room類中加一個實例方法IsNull,那當調用IsNul時,永遠也調用不到擴展方法,記住上面說的"找方法"的順序。
請斧正。