講過了委托,不得不講事件。
事件基於委托,為委托提供了一種發布/訂閱機制。
在發生其他類或對象關注的事情時,類或對象可通過事件通知它們。發送(或引發)事件的類稱為“發行者”,接收(或處理)事件的類稱為“訂戶”。
在典型的 C# Windows 窗體或 Web 應用程序中,可訂閱由控件(如按鈕和列表框)引發的事件。可使用 Visual C# 集成開發環境 (IDE) 來瀏覽控件發布的事件,選擇要處理的事件。IDE 會自動添加空事件處理程序方法和訂閱事件的代碼。
事件時對委托的封裝。
事件幫助解決委托封裝問題。事件位於委托的頂部,並提供封裝,使得目標源只能聽而不能完全控制的委托對象。
下圖顯示了事件的樣子: -
理解事件:
Button是一個類,當你點擊按鈕的時候,Click事件被觸發。
定時器是一個類,每毫秒tick事件被觸發。
下面通過一個例子來講述一下事件的應用。
定義兩個類CarDealer和Consumer。CarDealer類提供了一個新車到達時觸發的事件,Consumer類訂閱該事件,以獲得新車到達的通知。
事件發布程序:CarDealer類提供了EventHandler類型的NewCarInfo事件。事件一般使用帶兩個參數的方法。第一個參數是一個對象,包含事件的發送者;第二個參數提供了事件的相關信息。
你可能感到吃驚,沒有定義委托怎么就定義事件了??其實有了泛型委托EventHandler 委托后,就不再需要委托了。
EventHandler 的語法如下:
public delegate void EventHandler(Object sender,TEventArgs e) where TEventArgs : EventArgs
EventHandler定義了一個處理程序,返回void,接受兩個參數。第一個參數必須是object,第二個參數是T類型,對於T有一個約束,就是它必須派生自基類EventArgs。下面代碼的CarInfoEventArgs就派生自基類EventArgs.
EventArgs是包含事件數據的類的基類,此類不包含事件數據,在事件引發時不向事件處理程序傳遞狀態信息的事件會使用此類。如果事件處理程序需要狀態信息,則應用程序必須從此類派生一個類來保存數據。事件處理程序委托的標准簽名定義一個沒有返回值的方法,其第一個參數的類型為 Object,它引用引發事件的實例,第二個參數從 EventArgs 類型派生,它保存事件數據。 如果事件不生成事件數據,則第二個參數只是 EventArgs 的一個實例。 否則,第二個參數為從 EventArgs 派生的自定義類型,提供保存事件數據所需的全部字段或屬性。
EventHandler 是一種預定義委托,表示事件的事件處理程序方法,它與事件是否生成事件數據無關。 如果事件不生成事件數據,則用 EventArgs 替代泛型類型參數;否則,提供自己的自定義事件數據類型並用該類型替代泛型類型參數。
使用 EventHandler 的優點在於,如果事件生成事件數據,則無需編寫自己的自定義委托代碼。 此外,.NET Framework 只需一個實現就能支持 EventHandler ,這與替代泛型類型參數的事件數據類型無關。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace TestEvent { public class CarInfoEventArgs:EventArgs { public CarInfoEventArgs(string car) { this.Car = car; } public string Car{get; private set;} } public class CarDealer { public event EventHandlerNewCarInfo; public void NewCar(string car) { Console.WriteLine("CarDealer. new car {0}", car); if (NewCarInfo != null) { NewCarInfo(this, new CarInfoEventArgs(car)); } } } }
事件監聽器:Consumer類用作事件偵聽器。這個類訂閱了CarDealer類的事件,並定義了NewCarIsHere方法,該方法滿足EventHandler委托的要求,其參數類型是object和CarInfoEventArgs.
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace TestEvent { class Consumer { private string name; public Consumer(string name) { this.name = name; } public void NewCarIsHere(object sender, CarInfoEventArgs e) { Console.WriteLine("{0}: car {1} is new", name, e.Car); } } }
現在需要連接事件發布器和訂閱器。使用“+=”創建一個訂閱。使用“-=”取消了訂閱。使用代碼:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace TestEvent { class Program { static void Main(string[] args) { var dealer = new CarDealer(); var michael = new Consumer("Michael"); dealer.NewCarInfo += michael.NewCarIsHere; dealer.NewCar("Mercedes"); var nick = new Consumer("Nick"); dealer.NewCarInfo += nick.NewCarIsHere; dealer.NewCar("Ferrari"); dealer.NewCarInfo -= michael.NewCarIsHere; dealer.NewCar("Toyota"); } } } /*------------------------------------- 輸出結果: CarDealer. new car Mercedes Michael: car Mercedes is new CarDealer. new car Ferrari Michael: car Ferrari is new Nick: car Ferrari is new CarDealer. new car Toyota Nick: car Toyota is new ---------------------------------------*/
https://www.cnblogs.com/sjqq/p/6918006.html