委派與事件是 .NET 類型系統的皇冠上的明珠:委派實現「函式即資料」,事件在委派之上建立「發布-訂閱」鬆耦合協作模型,是觀察者模式的語言級原生支援。
// 宣告委派型別:定義可引用函式的簽名
public delegate void GreetingDelegate(string name);
// 具體函式
void EnglishGreeting(string n) => Console.WriteLine($"Morning, {n}");
void ChineseGreeting(string n) => Console.WriteLine($"早上好, {n}");
// 使用:將函式作為參數傳遞
void GreetPeople(string name, GreetingDelegate greeter) => greeter(name);
// 呼叫
GreetPeople("Jimmy", EnglishGreeting); // Morning, Jimmy
GreetPeople("張三", ChineseGreeting); // 早上好, 張三
del += Method 串聯多個函式,呼叫時依序執行MulticastDelegate 的密封類別,含 Invoke/BeginInvoke/EndInvoke直接暴露委派欄位兩大弊端:
= 覆寫,清除既有訂閱Invoke() 觸發,破壞封裝event 關鍵字解決:
public class GreetingManager {
// 僅允許 += / -=,編譯器產生私有委派欄位 + add_/remove_ 存取器
public event GreetingDelegate MakeGreet;
public void Greet(string name) => MakeGreet?.Invoke(name); // 安全觸發
}
// 使用
var gm = new GreetingManager();
gm.MakeGreet += EnglishGreeting; // 訂閱
gm.MakeGreet += ChineseGreeting; // 多播
gm.MakeGreet -= EnglishGreeting; // 退訂
gm.Greet("Jimmy"); // 觸發
// 來源
public event GreetingDelegate MakeGreet;
// 編譯器產生
private GreetingDelegate _makeGreet;
[MethodImpl(MethodImplOptions.Synchronized)]
public void add_MakeGreet(GreetingDelegate v) => _makeGreet = Delegate.Combine(_makeGreet, v);
[MethodImpl(MethodImplOptions.Synchronized)]
public void remove_MakeGreet(GreetingDelegate v) => _makeGreet = Delegate.Remove(_makeGreet, v);
Heater,狀態 = 溫度Alarm(聲音)、Display(視覺)
// 事件引數:攜帶領域資料
public class BoiledEventArgs : EventArgs {
public int Temperature { get; }
public BoiledEventArgs(int t) => Temperature = t;
}
// 被觀察者
public class Heater {
public event EventHandler Boiled; // 標準雙參數委派
protected virtual void OnBoiled(BoiledEventArgs e) => Boiled?.Invoke(this, e);
public void BoilWater() {
for (int t=0; t<=100; t++) {
if (t > 95) OnBoiled(new BoiledEventArgs(t));
}
}
}
// 觀察者
public class Alarm {
public void OnBoiled(object sender, BoiledEventArgs e) {
var h = (Heater)sender;
Console.WriteLine($"[{h.Model}] 警報:水溫 {e.Temperature}°C");
}
}
public class Display {
public static void OnBoiled(object sender, BoiledEventArgs e) {
Console.WriteLine($"顯示:水溫 {e.Temperature}°C");
}
}
// 組裝
var heater = new Heater { Model = "RealFire 001" };
var alarm = new Alarm();
heater.Boiled += alarm.OnBoiled;
heater.Boiled += Display.OnBoiled;
heater.BoilWater();
xxxEventHandlervoid (object sender, TEventArgs e),TEventArgs : EventArgsEventHandler 後綴(BoiledEventHandler → Boiled)protected virtual void OnXxx(XxxEventArgs e),衍生類可覆寫/擴展sender 傳遞 this,觀察者可回溯來源存取完整物件
// 匿名方法 (C# 2.0)
heater.Boiled += delegate(object s, BoiledEventArgs e) { ... };
// Lambda (C# 3.0+)
heater.Boiled += (s, e) => Console.WriteLine($"溫度: {e.Temperature}");
// 區域函式 (C# 7.0+)
void LocalHandler(object s, BoiledEventArgs e) => ...;
heater.Boiled += LocalHandler;
委派與事件是 .NET 非同步、UI、領域事件、微服務整合事件的基石。精通其機制與模式,是構建鬆耦合、可擴展、可測試系統的核心能力。