事件是 C# 實作觀察者模式的核心基礎設施。本文從委派本質出發,逐步推導事件的標準化模型,並對比委派與事件的異同。
delegate int MathOp(int a, int b); // 定義委派型別
static int Add(int a, int b) => a + b;
static int Mul(int a, int b) => a * b;
MathOp op1 = new MathOp(Add); // 完整寫法
MathOp op2 = Mul; // 方法群組轉換 (C# 2.0+)
Console.WriteLine(op1(100, 200)); // 300
Console.WriteLine(op2(100, 200)); // 20000
委派封裝「方法指標」,實例化時綁定目標方法,呼叫時如同呼叫該方法。
MathOp multi = Add;
multi += Mul; // 串聯
multi(2, 3); // 依序執行 Add 與 Mul,最終回傳 Mul 結果 (6)
// 1. 定義委派型別 (符合 EventHandler 模式)
public delegate void RegisterOkEventHandler(object sender, EventArgs e);
// 2. 宣告事件
public event RegisterOkEventHandler RegisterOK;
public class Student
{
public string Name { get; set; }
public event RegisterOkEventHandler RegisterOK;
public void Register()
{
Console.WriteLine("Register Method");
OnRegisterOK(EventArgs.Empty);
}
protected virtual void OnRegisterOK(EventArgs e)
{
RegisterOK?.Invoke(this, e); // 安全引發
}
}
static void Main()
{
var s1 = new Student { Name = "Student1" };
var s2 = new Student { Name = "Student2" };
s1.RegisterOK += Student_RegisterOK;
s2.RegisterOK += Student_RegisterOK;
s1.Register(); // 輸出: Register Method / Hello
s2.Register();
}
static void Student_RegisterOK(object sender, EventArgs e)
{
Console.WriteLine("Hello");
}
| 特性 | 委派 | 事件 |
|---|---|---|
| 可直接呼叫 | 是 | 否 (僅限宣告類別內部) |
| 外部可直接指派 (=) | 是 | 否 (僅允許 +=/-=) |
| 用途 | 一般方法回呼、策略模式 | 發布/訂閱、觀察者模式 |
| 封裝性 | 低 | 高 (防止外部任意引發/清除) |
EventHandler/EventHandler<T>)event 關鍵字宣告事件成員protected virtual void OnEventName(EventArgs e) 方法封裝引發邏輯事件在委派基礎上增加封裝限制,強制採用「發布者負責引發、訂閱者負責處理」的單向流向,是 C# 物件導向解耦的基石。下篇將深入預定義事件、EventHandler 模式與自訂事件參數。