CLR之委託的揭祕(一)

     初識委託:數組

         在以前的學習中咱們已經能夠把對象,值,數組看成參數傳遞給方法,可是有沒有可能把方法也看成參數傳遞給方法呢?有了這個想法因而就有了委託。方法看成一種參數去傳遞,可是方法有的有返回值有的沒有返回值,這如何處理?委託又用在什麼地方?經過這篇文章咱們來學習一下委託的用法
安全

        委託解密:ide

             在C#中要使用委託。必選先定義要使用的委託,在使用時須要建立該委託的一個或多個實例,如下示例展現瞭如何聲明委託            函數

1  /*
2      委託的安全性很是高,因此在聲明委託時,要聲明委託返回的類型和參數類型
3          */
4     //聲明返回類型爲double 兩個參數類型爲long的委託
5     public delegate double TwolongsOp(long first,long second);
6     //聲明返回類型爲string 無參的委託
7     public delegate string Getstring();
8     //聲明返回類型爲void 參數類型爲int的委託
9     public delegate void IntMethodInvoker(int x);
View Code

         因爲定義一個委託其實是定義一個類,但這個類前面必須加上delegate關鍵字,因此委託能夠定在類中的任何位置,也能夠在名稱空間中把委託看成頂層對象定義,表面上看,委託聲明只須要一句話public delegate double TwolongsOp(long first,long second);,但從CLR角度來看,委託其實是很複雜的,在使用委託以前先來看一下,底層是如何處理這一句話的。學習

         編譯器在讀取這行代碼時,實際上會自動爲其生成一個完整的類,這個類中包含有一個構造器和Invoke,BeginInvoke,EndInvoke方法。自動生成的這個類繼承自MulticastDelegate,因此這個類也繼承了MulticastDelegate的字段,屬性和方法。這個將在委託鏈中使用其中的一些方法。spa

          那麼通過CLR的自動編譯之後,咱們就能夠開始使用委託,下面代碼就是如何使用委託code

 1 class Program
 2     {
 3         //聲明返回類型爲string 無參的委託
 4         public delegate string Getstring();
 5         static void Main(string[] args)
 6         {
 7             int x = 40;
 8             //實例化委託,而且將int的ToString()方法看成參數傳遞給委託
 9             Getstring getstring = new Getstring(x.ToString);
10             //語法糖:簡化委託調用和使用new效果同樣
11             Getstring getstring1 = x.ToString;
12             //調用委託方法
13             Console.WriteLine(getstring());
14             //CLR生成的類中就包含的方法安全調用
15             Console.WriteLine(getstring1.Invoke());
16         }
17     }
View Code

           實際上代碼中使用getstring()方法調用和使用Invoke()調用是相同的,由於getstring()方法是委託類型的一個變量,C#編譯器會用getstring.Invoke()代替getstring(),若是爲了減小輸入量,只須要委託示例,就能夠只傳送地址,這稱爲委託判斷。對象

          委託鏈:blog

         鏈式語法在C#中很是常見,Linq就是典型的鏈式方法調用,而委託也支持鏈式方法調用,委託鏈指的就是委託對象的集合,利用鏈式調用集合中的委託所表明的所有方法,可是委託鏈是有限制和缺點的,委託鏈中間方法的返回值會被丟棄沒法獲取,因此委託返回值最好是void,若是是帶有返回值的,會返回最後一個方法的返回值。繼承

            舉個例子,若是我委託別人幫我去拿一個快遞,我又告訴他回來路上順便幫我帶份飯,這是兩件事情,若是這兩件事都只是去作,不須要拿到返回值,那麼委託鏈能夠知足,可是若是我要求兩個方法,第一個方法要把快遞返回到我手上,第二個方法飯也要返回到我手上,那麼就沒法獲取第一個方法的返回值,也就是說我只能拿到飯,而拿不到快遞。接下來看代碼比較

 1  //聲明返回類型爲string 無參的委託
 2         public delegate string Getstring();
 3         static void Main(string[] args)
 4         {
 5             //實例化委託鏈
 6             Getstring getstatus = null;
 7             //語法糖:支持+=/-=添加方法/移除方法
 8             getstatus += TakeExpress;
 9             getstatus += beltfood;
10             //得到結果
11             Console.WriteLine(getstatus());
12         }
13         //取快遞方法,返回的string看成實體類型看
14        public static string TakeExpress()
15         {
16             return "你的快遞是XX,已經爲你取了";
17         }
18          //帶飯方法,返回的string看成實體類型看
19         public static string beltfood()
20         {
21            return "爲你帶了一份黃燜雞米飯";
22         }
View Code

   

       兩個方法最終只輸出了最後一個方法的返回值,咱們獲得了一份黃燜雞米飯,可是快遞沒有獲得,因而咱們修改如下以上代碼,改成以下,能夠看到兩個方法都被執行了

 1  //聲明返回類型爲string 無參的委託
 2         public delegate void Getstring();
 3         static void Main(string[] args)
 4         {
 5             //實例化委託鏈
 6             Getstring getstatus = null;
 7             //語法糖:支持+=/-=添加方法/移除方法
 8             getstatus += TakeExpress;
 9             getstatus += beltfood;
10             //得到結果
11             getstatus();
12         }
13         public static void TakeExpress()
14         {
15             Console.WriteLine("你的快遞是XX,已經爲你取了");
16         }
17         public static void beltfood()
18         {
19             Console.WriteLine("爲你帶了一份黃燜雞米飯");
20         }
View Code

 

         匿名委託:

             匿名方法在.NET 中提升了 代碼的可讀性和優雅性。對於更多操做較少的方法直接寫爲匿名函數,這樣會大大提升代碼的可讀性。這裏有兩個值得注意的地方: 第一,不能使用跳轉語句跳轉到該匿名方法外,第二 不能使用ref,out修飾的參數,下面是一個匿名委託的調用

 

   //聲明返回類型爲string 無參的委託
        public delegate string Getstring(string str);
        static void Main(string[] args)
        {
             //直接在委託上完善方法
            Getstring Spkeak = delegate (string str)
            {
                if (str == "啞吧")
                {
                    return "我是啞吧,我不能說話";
                }
                return "我會說話"; 
            };

            Console.WriteLine(Spkeak("啞吧"));
View Code

 

         小結:

                 委託是一種比較經常使用的函數回掉方法,經常使用於某種狀況下觸發委託。

相關文章
相關標籤/搜索