C#事件与委托的区别
? 1. 委托
事件是利用委托來定義的,因此先解釋委托。委托其實是一個類,它與其他類如string(引用類型)等沒有本質區別,string代表的是字符串,委托則代表的是一類方法,這類方法具有相同返回類型和相同參數。例:有如下委托定義
public delegate void CalculatorHandler(int x,int y);?
從CalculatorHandler這個委托的定義可以看出,它反應的是一類方法,這類方法的返回類型是void,兩個參數是(int x,int y),因此以后所有具有這樣特征的方法都可以用這個委托來代替,現有以下這個方法:
static void Add(int x, int y){Console.WriteLine("x+y={0}",x+y);}這個方法,滿足委托所定義的這一類方法,但是如何利用委托來調用這個方法呢,首先要將這個方法賦值給這個委托才可以使用,就如普通的類賦值一樣,
CalculatorHandler calhandler = new CalculatorHandler(Add)
當然你也可以像給一個字符串賦值一樣,這樣給委托賦值:
CalculatorHandler calhander = Add;
當要調用這個方法的時候,你可以就像使用方法一樣使用委托,
calhander(3,4);
委托也可以綁定多個方法,當調用這個委托時,會調用所有已經綁定了的方法,如現在還有這樣的方法:
static void Multiply(int x, int y){Console.WriteLine("x*y={0}",x*y);}只需在calhandler基礎上多綁定個方法,具體語法:
calhander += Multiply;
這樣當調用
calhander(3,4);
會同時調用Add和Multiply這兩個方法,你也可以利用“-=”解綁方法:
calhander -= Multiply;
這樣再次調用這個委托,則只會調用Add這個方法。
2. 事件
一說到事件總會有發布者(publisher)和訂閱者(subscriber),發布者定義了一個事件,訂閱者訂閱了該事件(指的是當該事件觸發時,訂閱者做出什么樣的反應,即利用相應的函數去處理)。該函數的定義與定義該事件的委托必須配套。代碼如下:
public delegate void MessageEventHandler();class Publisher{public event MessageEventHandler MessageEvent;public void DoSomething(){Console.WriteLine("等待消息");Console.WriteLine("首長來啦!!!");OnMessageEvent();}public void OnMessageEvent(){if (MessageEvent != null){MessageEvent();}}}class Subscriber{public Subscriber(Publisher p){p.MessageEvent += Response;}public void Response(){Console.WriteLine("首場,辛苦了");} }class Program{static void Main(string[] args){Publisher p = new Publisher();Subscriber s = new Subscriber(p);p.DoSomething();Console.ReadKey();}} }這就是事件的基本用法,但是事件與委托到底有什么區別呢,從上面的代碼可以看出,事件是根據委托來定義的,
public event MessageEventHandler MessageEvent其實它是利用委托來規定訂閱者處理函數的類型(相同的返回類型和參數即為一類),然后方便在發布者自身的類中來觸發訂閱者的這些函數。
但是為什么要事件呢,要實現這些,我僅用委托也可以實現呀,如下代碼:
public delegate void MessageEventHandler();class Publisher{public MessageEventHandler MessageEvent;//為了方便,委托名與原來的事件名相同。// public event MessageEventHandler MessageEvent;public void DoSomething(){Console.WriteLine("等待消息");Console.WriteLine("首長來啦!!!");OnMessageEvent();}public void OnMessageEvent(){if (MessageEvent != null){MessageEvent();}}}class Subscriber{public Subscriber(Publisher p){p.MessageEvent += Response;}public void Response(){Console.WriteLine("首場,辛苦了");}}class Program{static void Main(string[] args){Publisher p = new Publisher();Subscriber s = new Subscriber(p);p.DoSomething();Console.ReadKey();} }這樣子也同樣可以產生相同的結果。
但是當客戶端如下調用呢?
Publisher p = new Publisher();Subscriber s = new Subscriber(p);p.DoSomething();p.MessageEvent();Console.ReadKey();客戶端是不是能隨意讓發布者產生事件,因此我們可否將發布者的委托定義為private,因為只有發布者的內部才能觸發事件嘛,其他人怎么可以?但是這樣訂閱者就無法訂閱了,那我們是否可以增加綁定和解除的函數來訂閱此委托呢?
public delegate void MessageEventHandler();class Publisher{private MessageEventHandler MessageEvent;// public event MessageEventHandler MessageEvent;public void DoSomething(){Console.WriteLine("等待消息");Console.WriteLine("首長來啦!!!");OnMessageEvent();}public void OnMessageEvent(){if (MessageEvent != null){MessageEvent();}}public void Add_MessageEvent(MessageEventHandler m){MessageEvent += m; }public void Reomove_MessageEvent(MessageEventHandler m){MessageEvent -= m;}}class Subscriber{public Subscriber(Publisher p){//p.MessageEvent += Response; p.Add_MessageEvent(Response);}public void Response(){Console.WriteLine("首場,辛苦了");}}class Program{static void Main(string[] args){Publisher p = new Publisher();Subscriber s = new Subscriber(p);p.DoSomething(); Console.ReadKey();}} }這樣就可以實現與事件一樣的功能,因此為了方便微軟為我們提供了事件訪問器,何為事件訪問器?
public delegate void MessageEventHandler();class Publisher{private MessageEventHandler MessageEvent;// public event MessageEventHandler MessageEvent;public event MessageEventHandler TestEvent{add{lock (MessageEvent){MessageEvent += value;}}remove{lock (MessageEvent){MessageEvent -= value;}}}public void DoSomething(){Console.WriteLine("等待消息");Console.WriteLine("首長來啦!!!");OnMessageEvent();}public void OnMessageEvent(){if (MessageEvent != null){MessageEvent();}}}class Subscriber{public Subscriber(Publisher p){p.TestEvent += Response;}public void Response(){Console.WriteLine("首場,辛苦了");}}class Program{static void Main(string[] args){Publisher p = new Publisher();Subscriber s = new Subscriber(p);p.DoSomething(); Console.ReadKey();} }以上的代碼就是利用事件訪問器來讓委托綁定訂閱者的方法,事件訪問器中的add和remove能自動編譯為+=和-=。
通過reflector,我們可以看到一個事件是如何定義的:
它是申明一個私有的委托:
private MessageEventHandler MessageEvent;另外利用兩個函數來綁定與解除訂閱者的方法。
?
轉載于:https://www.cnblogs.com/Celvin-Xu/p/3562506.html
總結
以上是生活随笔為你收集整理的C#事件与委托的区别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 集合框架(中)
- 下一篇: javascript对时间的处理