本文主要如下面幾個方面來詳細講解擴展方法:在C#3.0以前沒有擴展方法的狀態(或者你不會使用不知道擴展方法的時候)、擴展方法的語法及怎麼使用、怎麼正確的使用擴展方法;編程
1、首先說一下在C#3.0以前沒有擴展方法的狀態(或者你不會使用不知道擴展方法的時候)json
一、你們在項目中確定遇到相似這樣的需求且項目不少地方都會用到:1.須要對一個對象進行可空判斷;二、對一個集合或者對象進行序列化;三、時間格式轉換;四、List與DataTabel以前轉換等等。ide
我想在沒有擴展方法以前你們基本上都是作一個相似common的靜態公共靜態類,寫一些靜態方法供項目各個調用調用 如:this
public static class Common { /// <summary> /// 判斷是否爲Null或者空 /// </summary> /// <param name="obj">對象</param> /// <returns></returns> public static bool IsNullOrEmpty( object obj) { if (obj == null) return true; else { string objStr = obj.ToString(); return string.IsNullOrEmpty(objStr); } } }
其餘類調用公共方法spa
static void Main(string[] args) { string str = "lxsh"; Common.IsNullOrEmpty(str); }
經過這樣也能完成上面所說的幾個需求,可是讓人感受上端一直要顯示依賴Common這個靜態類,項目中就會大量充斥着這樣的代碼,看起來不那麼簡潔,並且也不利於後期的鏈式語法編程;3d
二、有時也會遇到這樣的狀況:你想對某個類型加一些行爲(方法),但你不能改變該類型的自己,由於是別人的代碼,遇到這樣狀況你可能會增長一個繼承接口,或者一個抽象類,或者經過代理模式封裝一次,這樣顯然能達到目的但都很麻煩;代理
以上解決辦法都是在沒有使用擴展方法以前的解決方案,當你學會了擴展方法,你可能會有更好的選擇;指針
2、 接下來咱們來講一下擴展方法的語法及使用code
一、擴展方法必須具有如下幾個特徵:orm
例如:
public static partial class Extensions { public static string ObjectToJSON(this object obj) { return JsonConvert.SerializeObject(obj, new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" }); } /// <summary> /// 判斷是否爲Null或者空 /// </summary> /// <param name="obj">對象</param> /// <returns></returns> public static bool IsNullOrEmpty(this object obj) { if (obj == null) return true; else { string objStr = obj.ToString(); return string.IsNullOrEmpty(objStr); } } }
二、怎麼使用擴展方法:
先引用擴展方法靜態類所在的命名空間,引用完成後,在調用的時候它在你對應類型實例上面有」智能感知「提示
三、擴展方法是怎麼被發現調用的
若是在using命令,將擴展方法引用到代碼中,擴展方法能夠像類一下不加限制地在代碼中使用。若是編譯器認爲一個表達試好像要使用一個實例方法,但沒有找到與這個方法調用兼容的實例方法,就會查找一個合適的擴展方法。它會檢查導入的全部命名空間和當前命名空間中全部的擴展方法,並匹配那些從表達式類型到擴展類型存在隱式轉換的擴展方法;
簡單一句話講:編譯器首先會查看這類型(包括父類)有沒有對應的該實例方法,若是有該實例方法他就不會執行擴展方法,若是沒有它就會找對應的擴展方法執行;
假若有一個 student類,它有一個實例方法say,再給他加一個擴展方法say
public class Student { public void Say() { Console.WriteLine("我是實例方法"); } } public static class Extensions { public static void Say(this Student student) { Console.WriteLine("我是擴展方法"); } }
static void Main(string[] args) { Student student = new Student(); student.Say(); Console.ReadKey(); }
執行結果爲:
還有一種狀況,對子類和父類同時加了一個同樣的擴展方法,且都引用了他們名詞空間,優先調用子類的擴展方法(一樣適用於接口父子關係)
public class Person { } public class Student:Person { public void Say() { Console.WriteLine("我是實例方法"); } } public static class Extensions { public static void Say(this Student student) { Console.WriteLine("我是擴展方法"); } public static void GetName(this Student student) { Console.WriteLine("我是子類擴展方法"); } public static void GetName(this Person student) { Console.WriteLine("我是父類擴展方法"); } }
static void Main(string[] args) { Student student = new Student(); student.Say(); student.GetName(); Console.ReadKey(); }
執行結果:
3、怎麼正確的使用擴展方法(建議)
接下來簡單講一下怎麼正確使用擴展方法:
1.若是在項目中使用擴展方法,首先須要要項目成員都熟悉擴展方法的使用
2.將擴展方法單獨放到一個單獨的命名空間裏,可有效的防止被誤用,建議擴展方法所屬擴展類儘可能用partial類(如針對Object的擴展方法命名Extensions.Object、針對string的擴展方法命名Extensions.String),方便代碼維護
例如:Extensions.Object、Extensions.String
namespace Lucky.Proect.Core.Extensions { public static partial class Extensions { public static string ObjectToJSON(this object obj) { return JsonConvert.SerializeObject(obj, new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" }); } /// <summary> /// 判斷是否爲Null或者空 /// </summary> /// <param name="obj">對象</param> /// <returns></returns> public static bool IsNullOrEmpty(this object obj) { if (obj == null) return true; else { string objStr = obj.ToString(); return string.IsNullOrEmpty(objStr); } } } }
namespace Lucky.Proect.Core.Extensions { public static partial class Extensions { [DebuggerStepThrough] //該特性是用在方法前面的,在想要跳過的方法前面加上 public static T FromJson<T>(this string jsonStr) { return string.IsNullOrEmpty(jsonStr) ? default(T) : JsonConvert.DeserializeObject<T>(jsonStr); } /// <summary> /// 指示指定的字符串是 null、空或者僅由空白字符組成。 /// </summary> [DebuggerStepThrough] //該特性是用在方法前面的,在想要跳過的方法前面加上 public static bool IsNullOrWhiteSpace(this string value) { return string.IsNullOrWhiteSpace(value); } /// <summary> /// 將Json字符串轉爲DataTable /// </summary> /// <param name="jsonStr">Json字符串</param> /// <returns></returns> public static DataTable ToDataTable(this string jsonStr) { return jsonStr == null ? null : JsonConvert.DeserializeObject<DataTable>(jsonStr); } } }
3.儘可能不在在object上面寫太多的擴展方法,寫以前要多加思考,否則在項目使用中任何類型智能提示出現一推擴展方法,看起來比較雜亂,針對int的擴展方法應該寫在int類型上,針對datetime的擴展方法應該寫在datetime類型上不該該都寫在object類型上
4.若是方法名在擴展類型中已經使用,就不要再用這個名稱了,由於寫了也無效;