學習Linq以前必需要了解的擴展方法

      本文主要如下面幾個方面來詳細講解擴展方法:在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);
            }
        }
    }
View Code

          其餘類調用公共方法spa

 static void Main(string[] args)
        {
            string str = "lxsh";
            Common.IsNullOrEmpty(str);
        }
View Code

        經過這樣也能完成上面所說的幾個需求,可是讓人感受上端一直要顯示依賴Common這個靜態類,項目中就會大量充斥着這樣的代碼,看起來不那麼簡潔,並且也不利於後期的鏈式語法編程;3d

        二、有時也會遇到這樣的狀況:你想對某個類型加一些行爲(方法),但你不能改變該類型的自己,由於是別人的代碼,遇到這樣狀況你可能會增長一個繼承接口,或者一個抽象類,或者經過代理模式封裝一次,這樣顯然能達到目的但都很麻煩;代理

          以上解決辦法都是在沒有使用擴展方法以前的解決方案,當你學會了擴展方法,你可能會有更好的選擇;指針

    2、 接下來咱們來講一下擴展方法的語法及使用code

      一、擴展方法必須具有如下幾個特徵:orm

  •             必須是在非嵌套的、非泛型的靜態類中
  •              必須在靜態類中的靜態方法
  •             至少要有一個參數
  •             第一個參數的前綴必須加this關鍵字且不能有任何修飾符(如:ref,out)且參數類型不能爲指針

 例如:

 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);
            }
        }

    }
View Code

    二、怎麼使用擴展方法:

         先引用擴展方法靜態類所在的命名空間,引用完成後,在調用的時候它在你對應類型實例上面有」智能感知「提示

 

    三、擴展方法是怎麼被發現調用的

    若是在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("我是擴展方法");
        }

    }
View Code
  static void Main(string[] args)
        {
            Student student = new Student();
            student.Say();    
           
            Console.ReadKey();
        }
View Code

執行結果爲:

     還有一種狀況,對子類和父類同時加了一個同樣的擴展方法,且都引用了他們名詞空間,優先調用子類的擴展方法(一樣適用於接口父子關係)

  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("我是父類擴展方法");
        }

    }
View Code
  static void Main(string[] args)
        {
            Student student = new Student();
            student.Say();
            student.GetName();
            Console.ReadKey();
        }
View Code

執行結果:

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);
            }
        }

    }
}
View Code

 

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);
        }
    }
}
View Code

    3.儘可能不在在object上面寫太多的擴展方法,寫以前要多加思考,否則在項目使用中任何類型智能提示出現一推擴展方法,看起來比較雜亂,針對int的擴展方法應該寫在int類型上,針對datetime的擴展方法應該寫在datetime類型上不該該都寫在object類型上

    4.若是方法名在擴展類型中已經使用,就不要再用這個名稱了,由於寫了也無效;

相關文章
相關標籤/搜索