初識委託:數組
在以前的學習中咱們已經能夠把對象,值,數組看成參數傳遞給方法,可是有沒有可能把方法也看成參數傳遞給方法呢?有了這個想法因而就有了委託。方法看成一種參數去傳遞,可是方法有的有返回值有的沒有返回值,這如何處理?委託又用在什麼地方?經過這篇文章咱們來學習一下委託的用法
安全
委託解密: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);
因爲定義一個委託其實是定義一個類,但這個類前面必須加上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 }
實際上代碼中使用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 }
兩個方法最終只輸出了最後一個方法的返回值,咱們獲得了一份黃燜雞米飯,可是快遞沒有獲得,因而咱們修改如下以上代碼,改成以下,能夠看到兩個方法都被執行了
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 }
匿名委託:
匿名方法在.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("啞吧"));
小結:
委託是一種比較經常使用的函數回掉方法,經常使用於某種狀況下觸發委託。