| 委派 | 參數 | 回傳 | 核心用途 | 典型 LINQ 方法 |
|---|---|---|---|---|
Predicate<T> | T | bool | 條件判斷/篩選 | List.FindAll, Array.Exists |
Func<T, TResult> | T | TResult | 轉換/計算/選取 | Select, Where (Func<T,bool>) |
Action<T> | T | void | 副作用執行/迴圈體 | List.ForEach, Array.ForEach |
皆支援多參數變體:Func<T1,T2,TResult> (最多 16 參數)、Action<T1,T2> 等。
List words = new() { "Apple", "Banana", "Cherry", "Date", "Elderberry" };
// 尋找長度 > 5 的第一個
string firstLong = words.Find(w => w.Length > 5); // "Banana"
// 取得所有符合條件
List longWords = words.FindAll(w => w.Length > 5); // ["Banana", "Cherry", "Elderberry"]
// 陣列版
string[] arr = words.ToArray();
bool hasShort = Array.Exists(arr, w => w.Length < 4); // true ("Date")
int idx = Array.FindIndex(arr, w => w.StartsWith("C")); // 2
關鍵點:語意明確「謂詞 = 真偽判斷」,API 多為 Find*/Exists/TrueForAll。
// Select 投影
var lengths = words.Select(w => w.Length); // IEnumerable
// 多參數:字典建構
var dict = words.ToDictionary(w => w, w => w.Length); // Func, Func
// 自訂邏輯
Func add = (a, b) => a + b;
int sum = add(3, 4); // 7
// 延遲執行陷阱
Func getRandom = () => Random.Shared.Next(); // 每次呼叫產生新值
int a = getRandom(), b = getRandom(); // 不同
// ForEach 執行動作
words.ForEach(w => Console.WriteLine(w.ToUpper()));
// 多參數 Action
Action writeColor = (msg, color) => {
var old = Console.ForegroundColor;
Console.ForegroundColor = color;
Console.WriteLine(msg);
Console.ForegroundColor = old;
};
writeColor("Error!", ConsoleColor.Red);
// 事件處理器本質
button.Click += (s, e) => MessageBox.Show("Clicked"); // EventHandler ≈ Action
Predicate startsWithA = s => s.StartsWith("A");
Predicate lengthGT5 = s => s.Length > 5;
Predicate both = s => startsWithA(s) && lengthGT5(s);
// 或擴充方法
public static Predicate And(this Predicate p1, Predicate p2) => x => p1(x) && p2(x);
Func trim = s => s.Trim();
Func upper = s => s.ToUpper();
Func pipeline = s => upper(trim(s)); // 或擴充 Compose
public class Processor {
private readonly Func _strategy;
public Processor(Func strategy) => _strategy = strategy;
public Output Run(Input input) => _strategy(input);
}
// 使用
var p1 = new Processor(i => i.Value * 2);
var p2 = new Processor(i => i.Value + 10);
static 方法群組或傳遞 state 參數:Action<object> act = (s) => DoWork((MyState)s);。Func/Action 為類別,結構體替代方案:delegate*<managed<T, TResult>> (C# 9 函數指標) 或 ValueFunc (社群庫),極少數極致場景才需考慮。Predicate<T> 就是 Func<T, bool>,隨意互換。」Predicate,投影/計算用 Func。static 方法,轉換為委派時**單例快取**(Roslyn 優化),零配置。Predicate、Func、Action 構成 C# 函數式編程的基石。掌握其**語意分工**、**組合模式**、**閉包效能特性**,能寫出更具表達力、可組合、高效能的代碼。下次寫 Where(x => ...) 時,腦中浮現的應是 Func<T, bool> 的精確簽名。