1. 程式人生 > WINDOWS開發 >C# Predicate與Func

C# Predicate與Func

C#有很多語法糖,有時使用時會覺得模稜兩可,

以前很少用Predicate,因為英文太長,不如Func實在,
在我感覺中,這兩個本該就是同一個東西。
但你會發現:
(1)List類的所有方法如Exists,Find,FindAll,FindIndex等全是接受Predicate<T>型別引數的。
(2)而List類實現的介面IEnumerable的所有擴充套件方法如All,Any,First,FirstOrDefault,Where等都是接受Func<TSource,bool>型別的引數的。

同樣是List中的方法,為什麼會使用不同的委託型別呢?
先看一下定義:
Func<T,bool> :表示有傳入T型別的引數,返回值為bool的委託

Predicate<T>:表示有傳入T型別的引數,返回值為bool的委託
在定義上不存在任何差別。
檢視Predicate和Func的定義如下:
public delegate bool Predicate<in T>(T obj);
public delegate TResult Func<in T,out TResult>(T arg);
當Func定義中TResult固定為bool,則兩個定義應該是完全一致,
List<T>中的方法引數本應該統一才對。
是微軟豆逼了麼,一定要寫成不一樣的?誰能告訴我為什麼!

下面驗證一下:

static void Main(string
[] args) { Predicate<int> myPredicate = i => i > 10; Func<int,bool> myFunc = i => i > 10; List<int> list = new List<int>(); list.Add(5); list.Add(9); list.Add(20); list.Add(30); List<int> newList = list.FindAll(myPredicate); List<int> newListFunc = list.Where(myFunc).ToList(); Console.ReadKey(); }

可以看到Predicate和Func接受的是完全相同的Lambada表示式,
而且執行結果newList和newListFunc完全相同。
此時用F12開啟Where的定義就可以看到如下程式碼:

//
// 摘要:
// 基於謂詞篩選值序列。
//
// 引數:
// source:
// 要篩選的 System.Collections.Generic.IEnumerable`1。
//
// predicate:
// 用於測試每個元素是否滿足條件的函式。
//
// 型別引數:
// TSource:
// source 中的元素的型別。
//
// 返回結果:
// 一個 System.Collections.Generic.IEnumerable`1,包含輸入序列中滿足條件的元素。
//
// 異常:
// T:System.ArgumentNullException:
// source 或 predicate 為 null。
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source,Func<TSource,bool> predicate);

由擴充套件函式Where的引數定義【Func<TSource,bool> predicate】可見,
Func<TSource,bool>即predicate,微軟就是這麼定義的。

結論:
Func<T,bool>是對delegate bool Predicate<T>(T obj)的簡化,
Predicate<T>又是對Func<T,bool>的簡化,
其實,就是一個東西。
List<T>中的方法應該統一引數。

附上以下內容:

Delegate至少0個引數,至多32個引數,可以無返回值,也可以指定返回值型別。這個是祖宗。
Func可以接受0個至16個傳入引數,必須具有返回值。
Action可以接受0個至16個傳入引數,無返回值。
Predicate只能接受一個傳入引數,返回值為bool型別。

原文連結:https://blog.csdn.net/rye_grass/java/article/details/66041423