一:什麼叫委托 通過反射發現,委托其實是一個類,繼承自System.MulticastDelegate,但是System.MulticastDelegate這個類是特殊類,不能被繼承 二:委托的聲明 委托可以聲明在類外面,可以聲明再類裡面 三:委托的實例和調用 private int GetSome ...
一:什麼叫委托
通過反射發現,委托其實是一個類,繼承自System.MulticastDelegate,但是System.MulticastDelegate這個類是特殊類,不能被繼承
二:委托的聲明
public delegate void NoReturnNoParaOutClass(); public class MyDelete { public delegate void NoReturnNoPara<T>(T t); public delegate void NoReturnNoPara(); public delegate void NoReturnWithPara(int x, int y); public delegate int WithReturnNoPara(); public delegate string WithReturnWithPara(out int x, ref int y); }
委托可以聲明在類外面,可以聲明再類裡面
三:委托的實例和調用
private int GetSomething() { return 1; } private int GetSomething2() { return 2; } private int GetSomething3() { return 3; } private void DoNothing() { Console.WriteLine("This is DoNothing"); } private static void DoNothingStatic() { Console.WriteLine("This is DoNothingStatic"); } public string ParaReturn(out int x, ref int y) { throw new Exception(); }View Code
//多種途徑實例化,要求傳遞一個參數類型,返回值都跟委托一致的方法 { WithReturnWithPara method = new WithReturnWithPara(ParaReturn); int x = 0; int y = 0; var dd = method.Invoke(out x, ref y); } //begininvoke { WithReturnNoPara method = new WithReturnNoPara(this.GetSomething); int iResult = method.Invoke(); iResult = method(); var result = method.BeginInvoke(null, null);//非同步調用 method.EndInvoke(result); } { NoReturnNoPara method = new NoReturnNoPara(this.DoNothing); //委托實力的調用,參數和委托約束的一致 method.Invoke(); //1 //method(); //2 //method.BeginInvoke(null, null); //3 //this.DoNothing(); //1,2,3都等同於this.DoNothing } { NoReturnNoPara method = new NoReturnNoPara(DoNothingStatic); } { NoReturnNoPara method = new NoReturnNoPara(Student.StudyAdvanced); } { NoReturnNoPara method = new NoReturnNoPara(new Student().Study); }
四:為什麼要使用委托
有時候我們聲明一個方法,直接調用蠻好的,為啥還要使用委托,然後還要先聲明,再實例化,再inovke調用呢?
下麵我們舉個例子,比如一個人問好這件事情,不同人問候方式不一樣,我們會先定義一個類型,如枚舉
public enum PeopleType { Chinese, America, Japanese }
然後通過不同的類型來判斷問候方式不同,如下
/// 為不同的人,進行不同的問候 /// 傳遞變數--判斷一下----執行對應的邏輯 /// </summary> /// <param name="name"></param> /// <param name="peopleType"></param> public void SayHi(string name, PeopleType peopleType) { switch (peopleType) { case PeopleType.Chinese: Console.WriteLine($"{name}晚上好"); break; case PeopleType.America: Console.WriteLine($"{name},good evening"); break; case PeopleType.Japanese: Console.WriteLine($"{name},&&%*^^***@@@&&&&"); break; default: throw new Exception("wrong peopleType"); //遇到異常報錯 } }
這樣做的好處是:以後如果增加公共邏輯等比較容易,但是如果類型比較多,這個方法會變成無限制改動,導致方法難以維護,於是很多人想著增加分支,就增加方法--不影響別的方法的思路來改善
public void SayHiChinese(string name) { Console.WriteLine($"{name}晚上好"); } public void SayHiJapanese(string name) { Console.WriteLine($"{name},&&%*^^***@@@&&&&"); } public void SayHiAmerican(string name) { Console.WriteLine($"{name},good evening"); }
然後上層判斷調用
這樣做的好處是:修改某個方法--不影響別的方法 ,但是缺點卻是:增加公共邏輯---多個方法就有很多重覆代碼
那麼我們想:既增加邏輯方便,又維護簡單,魚肉熊掌,如何兼得呢?
我們可以把相應的邏輯做為參數傳進來,這樣就解決了我們的問題
具體我們可以按照以下來做:
public void SayHiPerfact(string name, SayHiDeletegate method) { Console.WriteLine("增加開始日誌"); method.Invoke(name); Console.WriteLine("增加結束日誌"); } public delegate void SayHiDeletegate(string name);
然後調用的時候如下:
SayHiDeletegate method = new SayHiDeletegate(SayHiChinese);
這樣就做到了
1:邏輯解耦,方便維護
2:代碼重構,去掉重覆
其實這也是我們選擇使用委托的兩大優點
註意:以上我們純粹為了定義委托而定義委托,其實框架已經我們幫我們定義了Action 和Func這兩個委托,Action是沒有返回值,Func是有返回值的,這兩個委托類已經足夠我們使用了,所以有時候我們使用的時候,沒有必要自己再去定義,而直接使用即可