我很新的使用謂詞和剛學會寫:什麼是C#中的謂詞?
Predicate<int> pre = delegate(int a){ a %2 == 0 };
會有什麼謂語回報,它是如何有用的編程是什麼時候?
我很新的使用謂詞和剛學會寫:什麼是C#中的謂詞?
Predicate<int> pre = delegate(int a){ a %2 == 0 };
會有什麼謂語回報,它是如何有用的編程是什麼時候?
Predicate<T>
是一種功能性構造,它提供了一種基本測試某個給定對象是否屬實的簡便方法。
例如,假設我有一個類:
class Person {
public string Name { get; set; }
public int Age { get; set; }
}
現在讓我們假設我有一個List<Person> people
,我想知道是否有列表中的名爲奧斯卡的人。
,不使用Predicate<Person>
(或LINQ或任何花哨的東西),我總是可以做實現這一目標如下:
Person oscar = null;
foreach (Person person in people) {
if (person.Name == "Oscar") {
oscar = person;
break;
}
}
if (oscar != null) {
// Oscar exists!
}
這是好的,但後來我們說,我想檢查是否有名爲「露絲」的人?還是17歲的人?
使用Predicate<Person>
,我能找到使用少了很多代碼,這些事情:
Predicate<Person> oscarFinder = (Person p) => { return p.Name == "Oscar"; };
Predicate<Person> ruthFinder = (Person p) => { return p.Name == "Ruth"; };
Predicate<Person> seventeenYearOldFinder = (Person p) => { return p.Age == 17; };
Person oscar = people.Find(oscarFinder);
Person ruth = people.Find(ruthFinder);
Person seventeenYearOld = people.Find(seventeenYearOldFinder);
通知我說了很多更少的代碼,不是很多更快。開發人員常見的誤解是,如果某件事情需要一條線,那麼它的表現要比需要十條線的事情要好。但在幕後,採用Predicate<T>
的Find
方法畢竟只是枚舉。 Linq的許多功能也是如此。
那麼讓我們來看看在你的問題具體代碼:
Predicate<int> pre = delegate(int a){ return a % 2 == 0; };
在這裏,我們有一個Predicate<int> pre
接受一個int a
並返回a % 2 == 0
。這實質上是測試一個偶數。這意味着什麼:
pre(1) == false;
pre(2) == true;
依此類推。這也意味着,如果你有一個List<int> ints
,你想找到的第一個偶數,你可以這樣做:
int firstEven = ints.Find(pre);
當然,與您可以在代碼中使用任何其他類型的,這是一個很好想法給你的變量描述性的名字;所以我建議將以上pre
更改爲evenFinder
或isEven
之類的東西 - 沿着這些線。然後,上面的代碼是一個更加清晰:
int firstEven = ints.Find(evenFinder);
+1!到目前爲止,頁面上最清晰的答案。 – 2009-11-10 19:15:50
+1:寫得很好。我只想添加單行表單MSDN:「表示定義一組標準並確定指定對象是否符合這些標準的方法」 – 2009-11-10 19:26:03
令人驚歎。也解答了這個問題。 – 2009-11-10 19:27:27
根據定義,Predicate將始終返回一個布爾值。
Predicate<T>
基本上與Func<T,bool>
相同。
謂詞在編程中非常有用。它們通常用於允許您在運行時提供邏輯,可以根據需要儘可能簡單或複雜。
例如,WPF使用Predicate<T>
作爲輸入來過濾ListView的ICollectionView。這使您可以編寫可以返回布爾值的邏輯,以確定是否應在最終視圖中包含特定元素。邏輯可以非常簡單(只需在對象上返回一個布爾值)或非常複雜,全部由您決定。
只是可惜他們不是:) – leppie 2009-11-10 18:55:28
代表在編程中很有用。坦率地說,我發現Predicate這個名字非常無益,因爲這個問題明顯證明了這一點。如果你真的想描述一個謂詞,你會命名它Filter
不是什麼? [15個字符] – 2009-11-10 19:00:21
在C#中謂詞只是代表返回布爾值的代表。當你搜索對象集合並想要特定的東西時,它們是有用的(以我的經驗)。
我最近在使用第三方網頁控件(如treeviews)時遇到了他們,所以當我需要在樹中查找節點時,我使用.Find()方法並傳遞一個將返回特定節點我正在尋找。在你的例子中,如果'a'mod 2是0,委託將返回true。當然,當我在樹形視圖中查找節點時,我會比較它的名稱,文本和值屬性以進行匹配。當委託人發現匹配時,它返回我正在尋找的特定節點。
下面的代碼可以幫助你瞭解一些現實世界中使用的謂詞(名爲迭代器相結合)。
namespace Predicate
{
class Person
{
public int Age { get; set; }
}
class Program
{
static void Main(string[] args)
{
foreach (Person person in OlderThan(18))
{
Console.WriteLine(person.Age);
}
}
static IEnumerable<Person> OlderThan(int age)
{
Predicate<Person> isOld = x => x.Age > age;
Person[] persons = { new Person { Age = 10 }, new Person { Age = 20 }, new Person { Age = 19 } };
foreach (Person person in persons)
if (isOld(person)) yield return person;
}
}
}
或者,您可以不用foreach/yield循環來「返回persons.FindAll(isOld);」。 – 2017-08-13 02:14:34
這裏是我的博士辣椒,謂詞和安全功能的文章:http://blogs.msdn.com/ericlippert/archive/2008/08/19/tasty-beverages.aspx – 2009-11-10 21:30:21
@ 0A0D:我覺得如果問題不是特定於該版本,那麼標記問題「.net-2.0」是一個糟糕的主意。只需標記「.net」。 – 2010-08-28 00:04:11
@John:同意。它原來有2.0,所以我只是將.net和2.0合併到.net-2.0中。 – 2010-08-28 00:19:52