C#擴展方法知多少

      前言:上篇 序列化效率比拼——誰是最後的贏家Newtonsoft.Json 介紹了下序列化方面的知識。看過Demo的朋友可能注意到了裏面就用到過泛型的擴展方法,本篇打算總結下C#擴展方法的用法。博主打算分三個層面來介紹這個知識點,分別是:.Net內置對象的擴展方法、通常對象的擴展方法、泛型對象的擴展方法。html

     什麼是擴展方法?回答這個問題以前,先看看咱們通常狀況下方法的調用。相似這樣的通用方法你必定寫過:算法

        static void Main(string[] args)
        {

            string strRes = "2013-09-08 14:12:10";
            var dRes = GetDateTime(strRes);
        }

    
        //將字符串轉換爲日期
        public static DateTime GetDateTime(string strDate)
        {
            return Convert.ToDateTime(strDate);
        }

        //獲得非空的字符串
        public static string GetNotNullStr(string strRes)
        {
            if (strRes == null)
                return string.Empty;
            else
                return strRes;
        }

或者在項目中有一個相似Utils的工具類,裏面有多個Helper,例如StringHelper、XmlHelper等等,每一個Helper裏面有多個static的通用方法,而後調用的時候就是StringHelper.GetNotNullStr("aa");這樣。還有一種普通的用法就是new 一個對象,經過對象去調用類裏面的非static方法。反正博主剛開始作項目的時候就是這樣寫的。後來隨着工做經驗的累積,博主看到了擴展方法的寫法,立馬就感受本身原來的寫法太Low了。進入正題。ide

 

一、.Net內置對象的擴展方法工具

.Net內部也有不少定義的擴展方法,例如咱們Linq經常使用的Where(x=>x==true)、Select()等等。當你轉到定義的時候你很容易看出來:public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)。固然咱們也能夠給.Net對象新增擴展方法,好比咱們要給string對象加一個擴展方法(注意這個方法不能和調用的Main方法放在同一個類中):post

        public static string GetNotNullStr(this string strRes)
        {
            if (strRes == null)
                return string.Empty;
            else
                return strRes ;
        }

而後在Main方法裏面調用:測試

        static void Main(string[] args)
        {
            string strTest = null;
            var strRes = strTest.GetNotNullStr();
        }

簡單介紹:public static string GetNotNullStr(this string strRes)其中this string就表示給string對象添加擴展方法。那麼在同一個命名空間下面定義的全部的string類型的變量均可以.GetNotNullStr()這樣直接調用。strTest.GetNotNullStr();爲何這樣調用不用傳參數,是由於strTest就是做爲參數傳入到方法裏面的。你能夠試試。使用起來就和.Net framework定義的方法同樣:this

 

     固然除了string,你能夠給.Net內置的其餘對象加擴展方法,例如給DataGridViewRow的擴展方法:url

//DataGridViewRow的擴展方法,將當前選中行轉換爲對應的對象
        public static T ToObject<T>(this DataGridViewRow item) where T:class
        {
            var model = item.DataBoundItem as T;
            if (model != null)
                return model;
            var dr = item.DataBoundItem as System.Data.DataRowView;
            model = (T)typeof(T).GetConstructor(new System.Type[] { }).Invoke(new object[] { });//反射獲得泛型類的實體
            PropertyInfo[] pro = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public);
            Type type = model.GetType();
            foreach (PropertyInfo propertyInfo in pro)
            {
                if (Convert.IsDBNull(dr[propertyInfo.Name]))
                {
                    continue;
                }
                if (!string.IsNullOrEmpty(Convert.ToString(dr[propertyInfo.Name])))
                {
                    var propertytype = propertyInfo.PropertyType;
                }
            }
            return model;
        }
View Code

這樣看上去就像在擴展.Net Framework。有沒有感受有點高大上~spa

 

二、通常對象的擴展方法code

     和Framework內置對象同樣,自定義的對象也能夠增長擴展方法。直接上示例代碼:

    public class Person
    {
        public string Name { set; get; }
        public int Age { set; get; }
    }
        //Person的擴展方法,根據年齡判斷是不是成年人
        public static bool GetBIsChild(this Person oPerson)
        {
            if (oPerson.Age >= 18)
                return false;
            else
                return true;
        }

Main方法裏面調用:

var oPerson1 = new Person();
oPerson1.Age = 20;
var bIsChild = oPerson1.GetBIsChild();        

和string擴展方法相似,就很少作解釋了。

 

三、泛型對象的擴展方法

      除了上面兩種以外,博主發現其實能夠定義一個泛型的擴展方法。那麼,是否是全部的類型均可以直接使用這個擴展方法了呢?爲了保持程序的嚴謹,下面的方法可能沒有實際意義,當開發中博主以爲可能存在這種場景:

public static class DataContractExtensions
{
  //測試方法
  public static T Test<T>(this T instance) where T : Test2
  {
       T Res = default(T);
       try
       {
           Res.AttrTest = instance.AttrTest.Substring(0,2);
           //其餘複雜邏輯...


      }
      catch
      { }
      return Res;
  }

}

public class Test2
{
  public string AttrTest { set; get; }
}

 

使用擴展方法有幾個值得注意的地方:

(1)擴展方法不能和調用的方法放到同一個類中

(2)第一個參數必需要,而且必須是this,這是擴展方法的標識。若是方法裏面還要傳入其餘參數,能夠在後面追加參數

(3)擴展方法所在的類必須是靜態類

(4)最好保證擴展方法和調用方法在同一個命名空間下

 

      可能你第一次使用這個會以爲很彆扭。你也許會說擴展方法和我之前用的static方法不管從代碼實現仍是算法效率都差很少嘛,是的!確實差很少,但使用多了以後會發現它確實能幫你省去不少代碼。

相關文章
相關標籤/搜索