Delegate : 類似C語言中的函數指標(function pointer), 它包含了一個函数的原型(參數,返回值,呼叫方式)和該函数的内存位址. delegate是一種型別(class), 要宣告後才能使用.
例如, 我們在C語言中定義一個 callback函式, 可寫成:
typedef void (_stdcall* TouchFunc) (tOTM_Touch Touch);
等同於下面C#的寫法:
delegate void TouchEventFunc (tOTM_Touch Touch);
Event: event是C#是關鍵字, 這個關鍵字是一個修飾詞, 類似const,static等, 而event是用來修飾delegate. Event的實現需要透過delegate.
一個delegate被宣告為event(事件)後,除了在宣告事件的類別(Publisher)外,在其他的地方,只能利用+=、-=操作(即subscrib或unsubscribe), 而delegate則沒有這樣的限制
若要訂閱某事件, 可利用“+=", 訂閱或註冊某事件指定的delegate(所代理的函数).
publisher.RaiseCustomEvent += new CustomEventHandler(HandleCustomEvent);
或
publisher.RaiseCustomEvent += HandleCustomEvent; //C# 2.0 內新增的語法
若要取消訂閱事件, 使用減法指派運算子 (-=) :
publisher.RaiseCustomEvent -= HandleCustomEvent;
event為物件提供一種方式, 可在某些事情發生時,通知其他類別或物件.
傳送或引發事件的類別稱為 Publisher(發行者) ,而接收或處理事件的類別則稱為Subscriber(訂閱者)
跟Method(方法)不一樣的地方:
Event是主動, 有事件發生就作通知,你可以訂閱或不訂閱; 而Method是被動, 只能等待來呼叫,你不呼叫它就不會執行
下面為在C#中使用自訂Event的步驟:
在Publisher Class(傳送事件的類別)
- 宣告事件的Delegate型別
public delegate void ChangedEventHandler(object sender, CustomEventArgs e);
- 宣告事件
public event ChangedEventHandler Changed;
- 當事件發生時,觸發此事件
if (Changed != null) Changed(this, e);
在Subscriber Class(接收或處理事件的類別)
- 訂閱Publisher Class的事件
List.Changed += new ChangedEventHandler(ListChanged);
- 自訂事件發生時要作的動作
public void ListChanged(object sender, CustomEventArgs e) { // Do something.... }
下面的sample code 為時間變更事件的範例, 出處為 Delegates and Events in C# / .NET
using System; using System.Threading; namespace EventSample { /* ======== Event Publisher ============ */ // Our subject -- it is this class that other classes // will observe. This class publishes one event: // SecondChange. The observers subscribe to that event. public class Clock { // Private Fields holding the hour, minute and second private int _hour; private int _minute; private int _second; // The delegate named SecondChangeHandler, // which will encapsulate // any method that takes a clock object // and a TimeInfoEventArgs // object as the parameter and returns no value. It's the // delegate the subscribers must implement. public delegate void SecondChangeHandler( object clock, TimeInfoEventArgs timeInformation ); // The event we publish public event SecondChangeHandler SecondChange; // The method which fires the Event protected void OnSecondChange( object clock, TimeInfoEventArgs timeInformation ) { // Check if there are any Subscribers if (SecondChange != null) { // Call the Event SecondChange(clock, timeInformation); } } // Set the clock running, it will raise an // event for each new second public void Run() { for (; ; ) { // Sleep 1 Second Thread.Sleep(1000); // Get the current time System.DateTime dt = System.DateTime.Now; // If the second has changed // notify the subscribers if (dt.Second != _second) { // Create the TimeInfoEventArgs object // to pass to the subscribers TimeInfoEventArgs timeInformation = new TimeInfoEventArgs( dt.Hour, dt.Minute, dt.Second); // If anyone has subscribed, notify them OnSecondChange(this, timeInformation); } // update the state _second = dt.Second; _minute = dt.Minute; _hour = dt.Hour; } } } // The class to hold the information about the event // in this case it will hold only information // available in the clock class, but could hold // additional state information public class TimeInfoEventArgs : EventArgs { public TimeInfoEventArgs(int hour, int minute, int second) { this.hour = hour; this.minute = minute; this.second = second; } public readonly int hour; public readonly int minute; public readonly int second; } /* ==== Event Subscribers ======= */ // An observer. DisplayClock subscribes to the // clock's events. The job of DisplayClock is // to display the current time public class DisplayClock { // Given a clock, subscribe to // its SecondChangeHandler event public void Subscribe(Clock theClock) { theClock.SecondChange += new Clock.SecondChangeHandler(TimeHasChanged); } // The method that implements the // delegated functionality public void TimeHasChanged( object theClock, TimeInfoEventArgs ti) { Console.WriteLine("Current Time: {0}:{1}:{2}", ti.hour.ToString(), ti.minute.ToString(), ti.second.ToString()); } } /* ======= Test Application ========== */ // Test Application which implements the // Clock Notifier - Subscriber Sample public class Test { public static void Main() { // Create a new clock Clock theClock = new Clock(); // Create the display and tell it to // subscribe to the clock just created DisplayClock dc = new DisplayClock(); dc.Subscribe(theClock); // Get the clock started theClock.Run(); } } }
下面圖是為執行結果:
參考文章:
Delegates and events
MSDN - Events Tutorial