委派 是 C# 實現「方法作為參數傳遞」、「回呼」、「事件處理」的核心機制。它是型別安全的物件導向函數指標。本文從基礎語法、實例化方式、多播委派、匿名方法到 Lambda 表達式,系統建立完整知識圖譜。
// 宣告一個委派型別:接受兩個 int,回傳 int
public delegate int PerformCalculation(int x, int y);
// 宣告無回傳值、接受字串的委派
public delegate void Del(string message);
System.Delegate 的密封類別實例。public static void DelegateMethod(string message) {
Console.WriteLine(message);
}
// 實例化
Del handler = DelegateMethod; // 方法群組轉換
// 呼叫
handler("Hello World"); // 輸出: Hello World
public void MethodWithCallback(int p1, int p2, Del callback) {
callback($"The number is: {p1 + p2}");
}
// 使用
MethodWithCallback(1, 2, handler); // 輸出: The number is: 3
public class MethodClass {
public void Method1(string msg) { Console.WriteLine($"Instance: {msg}"); }
public void Method2(string msg) { Console.WriteLine($"Instance2: {msg}"); }
}
var obj = new MethodClass();
Del d1 = obj.Method1; // 封裝實例方法:持有 obj 引用
Del d2 = obj.Method2;
Del d3 = DelegateMethod; // 封裝靜態方法:僅持有方法指標
委派可透過 +/+= 組合,-/-= 移除。
Del all = d1 + d2; // 組合
all += d3; // 追加
all("Test"); // 依序呼叫 Method1, Method2, DelegateMethod
ref 參數,修改會傳遞給後續方法。all -= d1; // 移除 d1
Del single = all - d2; // 建立新委派,排除 d2
int count = all.GetInvocationList().Length; // 取得方法數量
==/!= 比較,比較調用清單是否相同。System.Delegate:編譯通過,運行時若實際型別不同則回傳 false。C# 2.0 引入,允許內嵌代碼區塊作為委派主體。
Del anon = delegate(string msg) {
Console.WriteLine($"Anonymous: {msg}");
};
anon("Hi"); // 輸出: Anonymous: Hi
delegate { ... }。goto、break、continue 跳出區塊。C# 3.0 引入,更簡潔的匿名函數語法,編譯為委派或運算式樹。
(參數列表) => 運算式或語句區塊
// 運算式 Lambda(隱含回傳)
Func add = (x, y) => x + y;
// 語句 Lambda
Action log = msg => {
var time = DateTime.Now;
Console.WriteLine($"{time}: {msg}");
};
// 無參數
Action sayHi = () => Console.WriteLine("Hi");
// 隱含型別參數(編譯器推斷)
var multiply = (int x, int y) => x * y;
| 特性 | 匿名方法 | Lambda 表達式 |
|---|---|---|
| 語法簡潔度 | 較冗長 | 極簡潔 |
| 型別推斷 | 需明確宣告參數型別 | 支援隱含型別 |
| 轉換為運算式樹 | 不支援 | 支援 (Expression<TDelegate>) |
| 參數可省略 | 可 delegate { } | 無參數需 () => |
var list = new List { 5, 2, 9, 1, 3 };
// 使用 Lambda 定義比較邏輯
list.Sort((a, b) => b.CompareTo(a)); // 降序
// 等價匿名方法
list.Sort(delegate(int a, int b) { return b.CompareTo(a); });
// 等價命名方法
list.Sort(CompareDesc);
static int CompareDesc(int a, int b) => b.CompareTo(a);
event 關鍵字在委派型別上增加封裝:僅允許 +=/-=,禁止外部直接呼叫或指派 =。EventHandler / EventHandler<TEventArgs>。Func<...>、Action<...>:內建泛型委派,減少自訂委派宣告。event 關鍵字,防止外部誤呼叫。out 參數:無法確定哪個方法被呼叫。delegate* 函數指標(.NET Core 3.0+ / C# 9.0+)以提升效能。委派是 C# 函數式程式設計、事件驅動架構、非同步模式的基石。從 delegate 關鍵字到 Lambda 表達式,語法演進始終圍繞「將行為作為資料傳遞」這一核心。熟練掌握委派的宣告、實例化、多播、閉包與型別推斷,是邁向 C# 專家的關鍵一步。