首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> C# 入門

C# 泛型委派三劍客:Predicate、Func、Action 精通指南

     編輯:C# 入門

總覽表

委派參數回傳核心用途典型 LINQ 方法
Predicate<T>Tbool條件判斷/篩選List.FindAll, Array.Exists
Func<T, TResult>TTResult轉換/計算/選取Select, Where (Func<T,bool>)
Action<T>Tvoid副作用執行/迴圈體List.ForEach, Array.ForEach

皆支援多參數變體:Func<T1,T2,TResult> (最多 16 參數)、Action<T1,T2> 等。

Predicate<T>:條件判斷專家


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。

Func<T, TResult>:轉換與投影核心


// 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(); // 不同

Action<T>:副作用執行器


// 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

進階組合模式

1. 謂詞組合


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);

2. Func 鏈式轉換


Func trim = s => s.Trim();
Func upper = s => s.ToUpper();
Func pipeline = s => upper(trim(s)); // 或擴充 Compose

3. 策略模式替代


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);

效能與記憶體

  • 委派實例為參考型別,捕獲變數會產生**閉包類別**(編譯器生成),導致額外配置。
  • 熱路徑避免 Lambda 捕獲:改用 static 方法群組或傳遞 state 參數:Action<object> act = (s) => DoWork((MyState)s);。
  • Func/Action 為類別,結構體替代方案:delegate*<managed<T, TResult>> (C# 9 函數指標) 或 ValueFunc (社群庫),極少數極致場景才需考慮。

常見誤區

誤區:「Predicate<T> 就是 Func<T, bool>,隨意互換。」
事實:型別不相容,無法隱性轉換。API 設計時選擇語意最貼切者:篩選用 Predicate,投影/計算用 Func。
誤區:「Lambda 總是建立委派物件。」
事實:不捕獲變數的 Lambda 編譯為 static 方法,轉換為委派時**單例快取**(Roslyn 優化),零配置。

結語

Predicate、Func、Action 構成 C# 函數式編程的基石。掌握其**語意分工**、**組合模式**、**閉包效能特性**,能寫出更具表達力、可組合、高效能的代碼。下次寫 Where(x => ...) 時,腦中浮現的應是 Func<T, bool> 的精確簽名。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved