引言
如果你看過了 C#中的委托和事件 一文,我想你對委托和事件已經有了一個基本的認識。但那些遠不是委托和事件的全部內容,還有很多的地方沒有涉及。本文將討論委托和事件一些更為細節的問題,包括一些大家常問到的問題,以及事件訪問器、異常處理、超時處理和異步方法調用等內容。
為什么要使用事件而不是委托變量?
在 C#中的委托和事件 中,我提出了兩個為什么在類型中使用事件向外部提供方法注冊,而不是直接使用委托變量的原因。主要是從封裝性和易用性上去考慮,但是還漏掉了一點,事件應該由事件發布者觸發,而不應該由客戶端(客戶程序)來觸發。這句話是什么意思呢?請看下面的范例:
NOTE:注意這里術語的變化,當我們單獨談論事件,我們說發布者(publisher)、訂閱者(subscriber)、客戶端(client)。當我們討論Observer模式,我們說主題(subject)和觀察者(observer)。客戶端通常是包含Main()方法的Program類。
class Program { static void Main(string[] args) { Publishser pub = new Publishser(); Subscriber sub = new Subscriber(); pub.NumberChanged += new NumberChangedEventHandler(sub.OnNumberChanged); pub.DoSomething(); // 應該通過DoSomething()來觸發事件 pub.NumberChanged(100); // 但可以被這樣直接調用,對委托變量的不恰當使用 } }// 定義委托public delegate void NumberChangedEventHandler(int count);// 定義事件發布者public class Publishser { private int count; public NumberChangedEventHandler NumberChanged; // 聲明委托變量 //public event NumberChangedEventHandler NumberChanged; // 聲明一個事件 public void DoSomething() { // 在這里完成一些工作 ... if (NumberChanged != null) { // 觸發事件 count++; NumberChanged(count); } } }// 定義事件訂閱者public class Subscriber { public void OnNumberChanged(int count) { Console.WriteLine("Subscriber notified: count = {0}", count); } }
上面代碼定義了一個NumberChangedEventHandler委托,然后我們創建了事件的發布者Publisher和訂閱者Subscriber。當使用委托變量時,客戶端可以直接通過委托變量觸發事件,也就是直接調用pub.NumberChanged(100),這將會影響到所有注冊了該委托的訂閱者。而事件的本意應該為在事件發布者在其本身的某個行為中觸發,比如說在方法DoSomething()中滿足某個條件后觸發。通過添加event關鍵字來發布事件,事件發布者的封裝性會更好,事件僅僅是供其他類型訂閱,而客戶端不能直接觸發事件(語句pub.NumberChanged(100)無法通過編譯),事件只能在事件發布者Publisher類的內部觸發(比如在方法pub.DoSomething()中),換言之,就是NumberChanged(100)語句只能在Publisher內部被調用。
新聞熱點
疑難解答