我对使用谓词非常陌生,刚刚学会了如何编写:
Predicate<int> pre = delegate(int a){ a %2 == 0 };
谓词将返回什么,它在编程时有什么用处?
Predicate<T>
是一种功能构造,提供了一种方便的方法,可以基本测试给定T
对象是否为真。
例如假设我有一个类:
class Person {
public string Name { get; set; }
public int Age { get; set; }
}
现在假设我有一个List<Person> people
,我想知道列表中是否有人叫 Oscar。
在不使用Predicate<Person>
(或 Linq 或任何花哨的东西)的情况下,我总是可以通过执行以下操作来完成此操作:
Person oscar = null;
foreach (Person person in people) {
if (person.Name == "Oscar") {
oscar = person;
break;
}
}
if (oscar != null) {
// Oscar exists!
}
这很好,但是假设我想检查是否有一个名为“Ruth”的人?还是一个17岁的人?
使用 a 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);
注意我说的代码少了很多,而不是快了很多。开发人员的一个常见误解是,如果某件事情需要一行,它必须比需要十行的事情表现得更好。但在幕后,Find
需要 a 的方法Predicate<T>
毕竟只是枚举。Linq 的许多功能也是如此。
那么让我们看一下您问题中的具体代码:
Predicate<int> pre = delegate(int a){ return a % 2 == 0; };
在这里,我们有一个Predicate<int> pre
接受int a
和返回的 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);
根据定义,谓词将始终返回一个布尔值。
Predicate<T>
基本相同Func<T,bool>
。
谓词在编程中非常有用。它们通常用于允许您在运行时提供逻辑,可以根据需要简单或复杂。
例如,WPF 使用 aPredicate<T>
作为过滤 ListView 的 ICollectionView 的输入。这使您可以编写可以返回布尔值的逻辑,以确定特定元素是否应包含在最终视图中。逻辑可以非常简单(只需在对象上返回一个布尔值)或非常复杂,完全取决于您。
以下代码可以帮助您了解谓词的一些实际使用(结合命名迭代器)。
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;
}
}
}
在 C# 中,谓词只是返回布尔值的委托。当您搜索一组对象并想要特定的东西时,它们很有用(根据我的经验)。
我最近在使用 3rd 方 Web 控件(如树视图)时遇到了它们,所以当我需要在树中查找节点时,我使用 .Find() 方法并传递一个谓词,该谓词将返回我所在的特定节点寻找。在您的示例中,如果 'a' mod 2 为 0,则委托将返回 true。当然,当我在树视图中查找节点时,我会比较它的名称、文本和值属性以进行匹配。当代理找到匹配项时,它会返回我正在寻找的特定节点。