.NET 框架內建 Action、Func、Predicate 涵蓋 99% 的委派場景,避免自訂委派型別,提高程式碼可讀性、相容性與標準化程度。
| 委派 | 參數 | 回傳值 | 適用場景 |
|---|---|---|---|
Action | 無 | void | 無參數、無回傳的動作 |
Action<T> | 1 個 | void | 單參數動作 |
Action<T1,T2> | 2 個 | void | 雙參數動作 |
... 最多 Action<T1..T16> | 16 個 | void | 多參數動作 |
Func<TResult> | 無 | TResult | 無參數、有回傳的函式 |
Func<T, TResult> | 1 個 | TResult | 單參數函式 |
... 最多 Func<T1..T16, TResult> | 16 個 | TResult | 多參數函式 |
Predicate<T> | 1 個 (T) | bool | 條件判斷、篩選 |
Comparison<T> | 2 個 (T, T) | int | 排序比較 |
Converter<TInput, TOutput> | 1 個 (TInput) | TOutput | 型別轉換 |
// 無參數
Action greet = () => Console.WriteLine("Hello World!");
greet();
// 單參數
Action log = msg => Console.WriteLine($"[LOG] {msg}");
log("應用程式啟動");
// 多參數
Action printTimes = (msg, n) => {
for (int i = 0; i < n; i++) Console.WriteLine(msg);
};
printTimes("重複列印", 3);
// 無參數有回傳
Func now = () => DateTime.Now;
Console.WriteLine(now());
// 單參數轉換
Func intToHex = x => x.ToString("X");
Console.WriteLine(intToHex(255)); // FF
// 多參數運算
Func hypot = (a, b) => Math.Sqrt(a*a + b*b);
Console.WriteLine(hypot(3, 4)); // 5
// 實際應用:LINQ 投影
var numbers = new[] { 1, 2, 3, 4, 5 };
var squares = numbers.Select(n => n * n); // Select 接受 Func
Predicate isEven = x => x % 2 == 0;
Predicate isNotNullOrEmpty = s => !string.IsNullOrEmpty(s);
// List 篩選
var list = new List { 1, 2, 3, 4, 5, 6 };
var evens = list.FindAll(isEven); // [2, 4, 6]
var firstEven = list.Find(isEven); // 2
var index = list.FindIndex(isEven); // 1
// Array 篩選
var arr = new[] { "apple", "", "banana", null, "cherry" };
var valid = Array.FindAll(arr, isNotNullOrEmpty); // ["apple", "banana", "cherry"]
var people = new List
{
new Person { Name = "Bob", Age = 30 },
new Person { Name = "Alice", Age = 25 },
new Person { Name = "Charlie", Age = 35 }
};
// 依年齡遞增
people.Sort((a, b) => a.Age.CompareTo(b.Age));
// 依名稱長度遞減
people.Sort((a, b) => b.Name.Length.CompareTo(a.Name.Length));
Action multiCast = null;
multiCast += s => Console.WriteLine($"Handler1: {s}");
multiCast += s => Console.WriteLine($"Handler2: {s}");
multiCast += s => Console.WriteLine($"Handler3: {s}");
multiCast("事件觸發");
// 輸出:
// Handler1: 事件觸發
// Handler2: 事件觸發
// Handler3: 事件觸發
// 移除特定處理器
multiCast -= s => Console.WriteLine($"Handler2: {s}"); // 注意:需保留相同委派實例才能移除
+=),事件模式請用 event 關鍵字list.FindAll(IsEven) 等同 list.FindAll(x => IsEven(x)),更簡潔
// 靜態方法群組轉換範例
static bool IsEven(int x) => x % 2 == 0;
var evens = list.FindAll(IsEven); // 自動轉為 Predicate
掌握內建委派,讓 C# 程式碼更符合慣例、更易維護、更好整合 LINQ 與標準庫。