C# 的事件模式建立在 Delegate (委派) 之上,實現「發佈-訂閱」模式。本文以最精簡的程式碼示範如何宣告委派、定義事件、引發事件與訂閱處理。
using System;
public class EventDemo
{
// 1. 定義委派型別:簽名為 (object sender, EventArgs e)
public delegate void ActionEventHandler(object sender, EventArgs e);
// 2. 宣告事件 (以 delegate 型別為型別)
public static event ActionEventHandler Action;
// 3. 受保護的虛擬方法:負責引發事件 (命名慣例 On + 事件名)
protected virtual void OnAction(object sender, EventArgs e)
{
// 使用 ?. 呼叫避免 null 參考 (C# 6+)
Action?.Invoke(sender, e);
}
// 4. 事件處理方法 (符合委派簽名)
public void HandlerA(object sender, EventArgs e)
{
Console.WriteLine("HandlerA 執行:" + DateTime.Now);
}
// 5. 訂閱與觸發示範
public void Demo()
{
// 訂閱
Action += new ActionEventHandler(HandlerA);
// 或簡寫:Action += HandlerA;
// 觸發
OnAction(this, EventArgs.Empty);
// 取消訂閱
Action -= HandlerA;
}
}
| 術語 | 角色 |
|---|---|
delegate | 定義方法簽名的「型別」,類似函數指標 |
event | 語言層級的封裝,限制外部只能 +=/-=,不能直接 = 或 Invoke |
sender | 事件來源物件,傳遞 this 讓處理者知道誰引發 |
EventArgs | 承載事件資料的基底類別,自訂資料請繼承它 |
public class PriceChangedEventArgs : EventArgs
{
public decimal OldPrice { get; }
public decimal NewPrice { get; }
public PriceChangedEventArgs(decimal oldPrice, decimal newPrice)
{
OldPrice = oldPrice; NewPrice = newPrice;
}
}
public class Stock
{
public event EventHandler<PriceChangedEventArgs> PriceChanged;
private decimal _price;
public decimal Price
{
get => _price;
set
{
if (_price != value)
{
var args = new PriceChangedEventArgs(_price, value);
_price = value;
PriceChanged?.Invoke(this, args);
}
}
}
}
Clicked、PriceChanged、Completed。protected virtual 方便衍生類別覆寫。EventHandler<TEventArgs> 泛型委派,免自訂 delegate 型別。var handler = Action; handler?.Invoke(...);