C# 事件模式包含三個核心角色:
EventArgs,封裝事件相關資料event 關鍵字,提供 OnEventName 觸發方法+= 訂閱public class EatEventArgs : EventArgs
{
public string RestaurantName; // 餐廳名稱
public decimal MoneyOut; // 預算金額
}
public delegate void EatEventHandler(object sender, EatEventArgs e);
public class Master
{
// 宣告事件
public event EatEventHandler EatEvent;
// 觸發事件的保護方法
public void OnEatEvent(EatEventArgs e)
{
EatEvent?.Invoke(this, e); // C# 6.0+ null 條件運算子
}
// 業務邏輯:主人餓了
public void Hungry(string restaurantName, decimal moneyOut)
{
var e = new EatEventArgs
{
RestaurantName = restaurantName,
MoneyOut = moneyOut
};
Console.WriteLine($"主人說:我餓了,要去 {e.RestaurantName} 吃飯,消費 {e.MoneyOut} 元");
OnEatEvent(e); // 引發事件
}
}
public class Servant
{
public void ArrangeFood(object sender, EatEventArgs e)
{
Console.WriteLine("\n僕人說:");
Console.WriteLine($"我的主人,您的命令是:");
Console.WriteLine($"吃飯地點 -- {e.RestaurantName}");
Console.WriteLine($"準備消費 -- {e.MoneyOut} 元");
Console.WriteLine("好的,正給您安排。。。。。。。。");
Console.WriteLine("主人,您的食物在這兒,請慢用");
}
}
public class God
{
public static void Main()
{
Master qinShiHuang = new Master();
Servant liSi = new Servant();
// 訂閱事件:指定李斯處理秦始皇的吃飯事件
qinShiHuang.EatEvent += new EatEventHandler(liSi.ArrangeFood);
// 觸發情境:秦始皇餓了,要去希爾頓大飯店,預算 5000 元
qinShiHuang.Hungry("希爾頓大飯店", 5000.0m);
}
}
主人說: 我餓了,要去希爾頓大飯店吃飯,消費 5000.0 元 僕人說: 我的主人,您的命令是: 吃飯地點 -- 希爾頓大飯店 準備消費 -- 5000.0 元 好的,正給您安排。。。。。。。。 主人,您的食物在這兒,請慢用
| 概念 | 說明 |
|---|---|
event 關鍵字 | 限制委派只能在類別內部觸發(Invoke),外部只能 +=/-= 訂閱/取消訂閱,防止外部任意廣播 |
sender 參數 | 事件來源物件(此例為 Master 實例),讓處理者識別發送者 |
EventArgs 繼承 | 慣例基類,提供無資料事件的基底型別(EventArgs.Empty) |
| 多播委派 | 一個事件可掛載多個處理方法,Invoke 依序呼叫 |
null 條件運算子 ?. | C# 6.0+ 語法糖,等同 if (EatEvent != null) EatEvent(this, e); |
add/remove 邏輯(如執行緒安全鎖定)EventHandler<TEventArgs> 泛型委派簡化宣告BeginInvoke/EndInvoke 或 Task 為基礎的非同步通知事件是 C# 觀察者模式的語言級實作。建議先掌握委派概念,再理解 event 的封裝意義。實務開發中,WinForms/WPF 控制項事件、ASP.NET Core 中介軟體管線、Entity Framework 狀態變更事件皆大量運用此模式。