委托
委托是一種數據類型,可以聲明委托類型變量。
委托是一種可以指向方法的數據類型。
聲明委托的方式:delegate返回值類型 委托類型名(參數) ? 比如 delegate void MyDel(int n)
注意這里的除了前面的delegate,剩下部分和聲明一個函數一樣,但是Mydel不是函數名,而是委托類型名
如何創建委托類型的對象:
MyDel sp = new Mydel (SayHello) //SayHello需要和MyDel的參數返回值一樣;
sp這個委托變量就指向SayHello這個方法。
注意不要寫成new Mydel (SayHello())因為加上()就是調用方法了
簡化的方法:MyDel sp = SayHello;//編譯器會給搞成new Mydel (SayHello),反編譯看看。
? ? 注意不要寫成MyDel sp = SayHello();
委托的使用:委托變量之間可以互相賦值,就是一個傳遞指向方法的過程;sp()就是調用指向的方法,如果有參數就傳遞參數。
委托:是一種指向方法的數據類型。 聲明的語法:delegate int MyDel2(int i,string s); MyDel2是一個數據類型;
? ? ? ?可以聲明一個變量指向和他類型相容的方法
? ? ? ? ? ? ? ?public delegate void MyDel(int n);
? ? ? ? ? ? ? static void M1(int a) { Console.WriteLine("M1"+a); }
? ? ? ? ? ? ? ?MyDel d1 = new MyDel(M1);//聲明MyDel類型的變量,指向一個指向M1方法的對象 //上面的代碼也可以簡化成MyDel d1 = M1;
? 不要把: MyDel d1 = new MyDel(M1); MyDel d1 = M1;
聲明成: MyDel d1 = new MyDel(M1()); MyDel d1 = M1();
因為加上括號就代表調用方法了! 拿到一個委托變量的時候MyDel d1 = M1;
加上括號就代表“執行指向的方法”,參數該怎么傳遞怎么傳遞 委托是引用類型,
可以為null,如果委托變量是null,那么如果調用的話,就會拋出NullReferenceException;
Func、Action
.Net中內置兩個泛型委托Func、Action(在“對象瀏覽器”的mscorlib的System下),
日常開發中基本不用自定義委托類型了。
Func是有返回值的委托;
Action是沒有返回值的委托
試驗一下用Func、 Action代替之前的委托
匿名方法
使用Delegate的時候很多時候沒必要使用一個普通的方法,因為這個方法只有這個Delegate會用,并且只用一次,這時候使用匿名方法最合適。
? 匿名方法就是沒有名字的方法。 MyDelegate p = delegate(int s){s=10;};
用匿名方法改造MyMax的例子。
lambda表達式
函數式編程,在Entity framework編程中用的很多
1、Action<int> a1 = delegate(int i) { Console.WriteLine(i); }; 可以簡化成(=>讀作goes to):
2、Action<int> a2 = (int i) => { Console.WriteLine(i); }; 還可以省略參數類型(編譯器會自動根據委托類型推斷):
3、Action<int> a3 = (i) => { Console.WriteLine(i); }; 如果只有一個參數還可以省略參數的小括號(多個參數不行) Action<int> a4 = i => { Console.WriteLine(i); };
4、如果委托有返回值,并且方法體只有一行代碼,這一行代碼還是返回值,那么就可以連方法的大括號和return都省略:
Func<int, int, string> f1 = delegate(int i, int j) { return "結果是" + (i + j); }; Func<int,int,string> f2= (i,j)=>"結果是"+(i+j);
5、普通匿名類型也是一樣用lambda表達式
委托深入
集合常用擴展方法:
Where(支持委托)、Select(支持委托)、Max、Min、OrderBy
First(獲取第一個,如果一個都沒有則異常)
FirstOrDefault(獲取第一個,如果一個都沒有則返回默認值)
Single (獲取唯一一個,如果沒有或者有多個則異常)
SingleOrDefault (獲取唯一一個,如果沒有則返回默認值,如果有多個則異常)
關于orderby、關于where的深入分析 ToList、ToArray
委托的組合
委托對象可以“+相加”,調用組合后的新委托對象會依次調用被組合起來的委托:MyDel m5 = m1+m2+m3;
組合的委托必須是同一個委托類型
(*)委托的“-”則是從組合委托中把委托移除;
(*)委托如果有返回值,則有一些特殊。
委托的組合一般是給事件用的,用普通的委托的時候很少用
事件
案例:定一個Person類,定一個監聽年齡變化的事件,當本命年的時候祝賀一下。
觸發事件的地方要判斷一下是不是事件null
事件語法:event Mydelegate mdl;
加了event關鍵字實現事件機制的好處:
用了event事件,不可以修改事件已經注冊的值;不可以冒充進行事件通知了。只能+=、-=!
委托與事件總結
委托的作用:
占位,在不知道將來要執行的方法的具體代碼時,可以先用一個委托變量來代替方法調用(委托的返回值,參數列表要確定)。在實際調用之前,需要為委托賦值,否則為null。
事件的作用:
事件的作用與委托變量一樣,只是功能上比委托變量有更多的限制。
(比如:1.只能通過+=或-=來綁定方法(事件處理程序)2.只能在類內部調用(觸發)事件。)
(面試題)事件和委托的關系:事件由一個私有的委托變量和add_***和remove_***方法組成;
事件的非簡化寫法:聲明一個私有的委托變量和add、remove方法。
委托和事件的區別和關系
錯誤的說法“事件是一種特殊的委托”
委托用的比較多,事件只有開發WinForm、WPF的時候用的才比較多,而WinForm、WPF則不是學習重點。掌握“事件和語法”、“委托和事件的關系和區別(面試題)”即可。
事件監聽的代碼的快速生成;WinForm中的事件簡單分析(誰調用的Onclick方法)
事件、索引器、屬性本質上都是方法。(面試題)接口中可以定義什么?接口中只可以定義方法。接口中也可以定義“事件、索引器、屬性”,因為他們本質上也都是方法。