委派 是 C# 中「型別安全的函式指標」,它定義一個方法簽章 (參數類型、回傳類型),讓你能將符合該簽章的方法當作「物件」傳遞、儲存、動態調用。本文以通俗語言拆解委派核心概念、宣告、實例化、多播與實務應用。
// 定義一個委派型別:接受 int,回傳 int
public delegate int IntOperation(int x);
這等同於定義一個「介面」:int Method(int x)。任何符合此簽章的方法 (靜態/實例、公開/私有) 都可指派給此委派變數。
using System;
public delegate int IntOperation(int x); // 1. 宣告委派型別
class Program {
// 2. 目標方法們
static int Double(int n) => n * 2;
static int Square(int n) => n * n;
static int AddTen(int n) => n + 10;
static void Main() {
// 3. 實例化 (方法群組轉換,等同 new IntOperation(Double))
IntOperation op1 = Double;
IntOperation op2 = Square;
// 4. 呼叫
Console.WriteLine($"Double(3) = {op1(3)}"); // 6
Console.WriteLine($"Square(3) = {op2(3)}"); // 9
// 5. 多播委派:串聯多個方法,依序執行,回傳最後一個結果
IntOperation multi = Double;
multi += Square; // 串聯
multi += AddTen;
int result = multi(3); // 依序執行 Double(3)→6, Square(3)→9, AddTen(3)→13
Console.WriteLine($"Multi(3) 最後結果 = {result}"); // 13
// 移除
multi -= Square;
result = multi(3); // Double(3)→6, AddTen(3)→13
Console.WriteLine($"移除 Square 後 = {result}"); // 13
// 遍歷調用清單 (進階)
foreach (IntOperation d in multi.GetInvocationList()) {
Console.WriteLine($" 調用 {d.Method.Name}(3) = {d(3)}");
}
}
}
| 特性 | 說明 |
|---|---|
| 型別安全 | 編譯期檢查參數/回傳型別,不匹配直接報錯,避免執行期崩潰。 |
| 多播 | `+=` 串聯,`-=` 移除。調用時依序執行所有目標,回傳值為最後一個目標的回傳值。若中間拋出例外,後續不執行。 |
| 不可變性 | `+=`/`-=` 實際產生新的委派實例,原實例不變 (類似字串)。 |
| 目標物件綁定 | 實例方法綁定時會捕獲 `this` (目標物件),靜態方法則無。 |
| 協變/逆變 | C# 支援委派回傳型別協變、參數型別逆變 (如 `Func |
.NET Framework 3.5+ 內建常用委派,無需自行宣告:
Func<T1, T2, ..., TResult>:有回傳值 (最多 16 參數)。Action<T1, T2, ...>:無回傳值 (void)。Predicate<T>:回傳 `bool`,單一參數。| 比較點 | 委派 | 介面 | 事件 |
|---|---|---|---|
| 本質 | 單一方法簽章的型別 | 多成員契約 | 基於委派的發布/訂閱封裝 |
| 適用場景 | 回呼、策略模式、LINQ、非同步 | 多行為協定、依賴倒置 | 物件狀態變更通知 (Observer) |
| 封裝性 | 公開調用、可任意指派 | 僅公開介面成員 | 僅允許 `+=`/`-=`,不可直接呼叫/清空 |
委派是 C# 函數式程式設計、事件驅動、非同步模型的基石。熟練掌握 `Func`/`Action`、Lambda、多播機制,能寫出更彈性、可測試、符合開閉原則的程式碼。