先說結論
委托:
1.一種可以把函數名當參數傳遞的類型
2.可以通過delegateName()直接觸發
3. 可以賦值。
多播委托:
1可以傳遞多個函數名,調用時會運行多個函數
2.可以通過delegateName()直接觸發
3.可以賦值。
事件:
1.類似多播委托,本質更像是委托的一個實例,但是具有封裝性。
2.不能像委托一樣直接觸發,只能通過事件相關函數觸發。
3.不像委托一樣可以直接賦值,但是可以通過+= 和 -=增加和移除函數。
4.可以實現發布訂閱者模式。
委托實例(標粗注意):
我們希望給委托加一個事件,一個中國人問好,並且觸發委托
class Program { public delegate void SayDelegate(string name); public class ChinesePeople { public void SayChinese(string name) { Console.WriteLine("你好" + name); } public void Greet(string name, SayDelegate action) { action(name); } } static void Main(string[] args) { string name = "張三"; ChinesePeople cp = new ChinesePeople();
//給委托賦值 SayDelegate delegate1 = cp.SayChinese;
//只傳一個函數名時,兩種寫法都可以
delegate1(name); cp.Greet(name,delegate1); cp.Greet(name,cp.SayChinese);
Console.ReadKey(); } }
結果:
你好張三
你好張三
你好張三
多播委托實例一:
我們希望委托讓一個中國人和一個英國人問好,這時候我們通過+=添加函數。
public delegate void SayDelegate2(string name); public class ChinesePeople { public void SayChinese(string name) { Console.WriteLine("你好" + name); } } public class EnglishPeople { public void SayEnglish(string name) { Console.WriteLine("hello" + name); } } class Program { static void Main(string[] args) { string name = "張三"; ChinesePeople cp = new ChinesePeople(); EnglishPeople ep = new EnglishPeople(); SayDelegate2 delegate1 = cp.SayChinese; delegate1 += ep.SayEnglish; delegate1(name); Console.ReadLine(); } }
結果:
你好張三
hello張三
多播委托實例二:
delegate1(name)看起來太簡潔了,我們根本不知道這個委托是要干什么的, 如果我們跟第一個一樣,把委托封裝到一個方法里調用呢?這樣我們就知道這個委托負責做什么的啦
public delegate void SayDelegate(string name); public class ChinesePeople { public void SayChinese(string name) { Console.WriteLine("你好" + name); } } public class EnglishPeople { public void SayEnglish(string name) { Console.WriteLine("hello" + name); } } public class GreetEvent { public void Greet(string name, SayDelegate2 action) { action(name); } } class Program { static void Main(string[] args) { string name = "a"; ChinesePeople cp = new ChinesePeople(); EnglishPeople ep = new EnglishPeople(); GreetEvent gEvent= new GreetEvent(); SayDelegate delegate1 = cp.SayChinese; delegate1 += ep.SayEnglish;
//這樣我們就知道這是在“Greet”問好 gEvent.Greet(name, delegate1); Console.ReadLine(); } }
寫完我們發現,wow竟然需要這么多聲明?這完全不符合我們面向對象封裝性的原則呀!我們能不能把委托、事件寫到一起呢?
於是事件(Event)出來了。
事件實例:
模擬情景:主人來了,主人問好之后,兩個客人——一個中國人一個英國人也向主人問好。
(這就是經典的發布訂閱模式,發布者是主人,訂閱者是中國人和英國人。發布者做出的行動之后,訂閱者也做出相應的行為)
所以我們新建一個主人類,封裝委托,事件,和觸發事件的函數。
public class Master { public delegate void SayDelegate(string name); public event SayDelegate SayEvent; public void Greet(string name) { if (SayEvent != null) { SayEvent(name); } } } public class ChinesePeople { public void SayChinese(string name) { Console.WriteLine("你好" + name); } } public class EnglishPeople { public void SayEnglish(string name) { Console.WriteLine("hello" + name); } } class Program { static void Main(string[] args) { string name = "張三"; ChinesePeople cp = new ChinesePeople(); EnglishPeople ep = new EnglishPeople(); Master m = new Master(); m.SayEvent += cp.SayChinese; m.SayEvent += ep.SayEnglish; m.SayEvent -= ep.SayEnglish; m.Greet(name); Console.ReadLine(); } }
注意點:1. 事件不能像委托直接delegate(name)調用,也就是說m.SayEvent()是不可行的。只能通過調用函數去觸發事件
2.事件不能直接賦值,只能通過+=和-=增加和移除函數
突然寫這個文章是因為工作中遇到的需要傳函數名進行封裝的方法~記錄一下,也希望能給初學者帶來幫助。