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
沒有留言:
張貼留言