委派是型別安全的物件導向函數指標,可參考靜態/實例方法。三步驟:宣告、實例化、呼叫。
// 1. 宣告委派型別
public delegate void MyDelegate(string name);
// 2. 目標方法
public static void MyDelegateFunc(string name)
{
Console.WriteLine($"Hello, {name}");
}
// 3. 實例化並呼叫
public static void Main()
{
MyDelegate md = new MyDelegate(MyDelegateFunc); // 或簡寫 MyDelegate md = MyDelegateFunc;
md("sam1111"); // 呼叫委派
}
this)。+/+= 組合,-/-= 移除,依序呼叫。delegate void MyDelegate(string s);
static void Hello(string s) => Console.WriteLine($"Hello, {s}!");
static void Goodbye(string s) => Console.WriteLine($"Goodbye, {s}!");
static void Main()
{
MyDelegate a = Hello, b = Goodbye;
MyDelegate c = a + b; // 組合
MyDelegate d = c - a; // 移除 a
a("A"); // Hello, A!
b("B"); // Goodbye, B!
c("C"); // Hello, C! -> Goodbye, C!
d("D"); // Goodbye, D!
}
事件是基於委派的發佈-訂閱機制,限制外部只能 +=/-=,不能直接呼叫或覆寫。
public delegate void MyEventHandler(object sender, MyEventArgs e);EventArgs),無參數可直接用 EventArgs。event 關鍵字宣告事件成員。+= 訂閱,-= 取消訂閱。protected virtual void OnEventName(EventArgs e) 觸發方法(檢查 null)。OnEventName 引發事件。using System;
public class EventTest
{
// 1. 委派
public delegate void MyEventHandler(object sender, EventArgs e);
// 2. 事件參數類別(此處無額外資料,直接用 EventArgs)
// 3. 事件處理方法
public class MyEventCls
{
public void MyEventFunc(object sender, EventArgs e)
{
Console.WriteLine("My event is ok!");
}
}
// 4. 事件宣告
private event MyEventHandler myEvent;
private readonly MyEventCls myEcls = new MyEventCls();
public EventTest()
{
// 5. 訂閱
myEvent += new MyEventHandler(myEcls.MyEventFunc);
}
// 6. 觸發方法
protected virtual void OnMyEvent(EventArgs e)
{
myEvent?.Invoke(this, e); // C# 6.0+ null 條件運算子
}
// 7. 對外引發
public void RaiseEvent()
{
OnMyEvent(EventArgs.Empty);
}
public static void Main()
{
var et = new EventTest();
Console.Write("Please input 'a': ");
string s = Console.ReadLine();
if (s == "a") et.RaiseEvent();
else Console.WriteLine("Error");
}
}
| 特性 | 委派 | 事件 |
|---|---|---|
| 關鍵字 | delegate | event |
| 外部可直接呼叫 | 是 | 否(僅能 +=/-=) |
| 外部可直接指派 (=) | 是 | 否 |
| 用途 | 回呼、策略、多播 | 通知、解耦、發佈-訂閱 |
EventHandler<TEventArgs> 泛型委派,避免自訂委派型別。?.Invoke() 簡化 null 檢查。record 型別作為事件參數(不可變、語意清晰)。