【问题标题】:What is a predicate in c#? [duplicate]c#中的谓词是什么? [复制]
【发布时间】:2010-12-15 04:22:23
【问题描述】:

我对使用谓词非常陌生,刚刚学会了如何编写:

Predicate<int> pre = delegate(int a){ a %2 == 0 };

谓词将返回什么,在编程时它有什么用处?

【问题讨论】:

    标签: c# .net vb.net predicate


    【解决方案1】:

    Predicate&lt;T&gt; 是一个函数式构造,它提供了一种方便的方法来基本测试给定的T 对象是否为真。

    例如假设我有一个班级:

    class Person {
        public string Name { get; set; }
        public int Age { get; set; }
    }
    

    现在假设我有一个List&lt;Person&gt; people,我想知道列表中是否有人叫 Oscar。

    没有使用Predicate&lt;Person&gt;(或Linq,或任何花哨的东西),我总是可以通过执行以下操作来完成:

    Person oscar = null;
    foreach (Person person in people) {
        if (person.Name == "Oscar") {
            oscar = person;
            break;
        }
    }
    
    if (oscar != null) {
        // Oscar exists!
    }
    

    这很好,但是假设我想检查是否有一个名为“Ruth”的人?还是17岁的人?

    使用Predicate&lt;Person&gt;,我可以使用更少的代码找到这些东西:

    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&lt;T&gt;Find 方法毕竟只是枚举。 Linq 的许多功能也是如此。

    那么我们来看看你问题中的具体代码:

    Predicate<int> pre = delegate(int a){ return a % 2 == 0; };
    

    这里我们有一个Predicate&lt;int&gt; pre,它接受一个int a并返回a % 2 == 0。这本质上是对偶数的测试。这意味着:

    pre(1) == false;
    pre(2) == true;
    

    等等。这也意味着,如果你有一个List&lt;int&gt; ints 并且你想找到第一个偶数,你可以这样做:

    int firstEven = ints.Find(pre);
    

    当然,与您可以在代码中使用的任何其他类型一样,为您的变量提供描述性名称是个好主意;所以我建议将上面的pre 更改为evenFinderisEven 之类的东西——类似的东西。那么上面的代码就清晰了很多:

    int firstEven = ints.Find(evenFinder);
    

    【讨论】:

    • +1 来自我!到目前为止,页面上最清晰的答案。
    • +1:写得很好。我只想在MSDN中添加一个衬线形式:“表示定义一组标准并确定指定对象是否符合这些标准的方法”
    • 太棒了。也喜欢这个问题。
    • 很棒的评论!您在 2009 年回答,在 2019 年仍然具有相关性和帮助。
    • 世界因为有你这样的人而依然美丽。很好的解释,谢谢你的回答
    【解决方案2】:

    根据定义,谓词将始终返回布尔值。

    Predicate&lt;T&gt;Func&lt;T,bool&gt;基本相同。

    谓词在编程中非常有用。它们通常用于允许您在运行时提供逻辑,可以根据需要简单或复杂。

    例如,WPF 使用Predicate&lt;T&gt; 作为过滤 ListView 的 ICollectionView 的输入。这使您可以编写可以返回布尔值的逻辑,以确定特定元素是否应包含在最终视图中。逻辑可以非常简单(只需在对象上返回一个布尔值)或非常复杂,完全取决于您。

    【讨论】:

    • 委托在编程中很有用。坦率地说,我发现 Predicate 这个名字非常无用,因为这个问题清楚地证明了这一点。如果您真的想描述谓词的作用,您可以将其命名为 Filter.
    • @Ed:我认为他是在暗示他们不只是 Func
    • 它们不是同一类型,因此不能相互转换。
    • 将其命名为 Predicate 对我来说非常有意义...这是一个用于分支逻辑的布尔值函数...
    【解决方案3】:

    以下代码可以帮助您了解谓词的一些实际用法(结合命名迭代器)。

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

    【讨论】:

    • 或者,您可以“返回 people.FindAll(isOld);”,而不是 foreach/yield 循环。
    【解决方案4】:

    在 C# 中,谓词只是返回布尔值的委托。当您搜索一组对象并想要特定的东西时,它们很有用(根据我的经验)。

    我最近在使用 3rd 方 Web 控件(如树视图)时遇到了它们,所以当我需要在树中查找节点时,我使用 .Find() 方法并传递将返回特定节点的谓词我在找。在您的示例中,如果 'a' mod 2 为 0,则委托将返回 true。当然,当我在树视图中查找节点时,我会比较它的名称、文本和值属性以进行匹配。当代理找到匹配项时,它会返回我正在寻找的特定节点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-20
      • 1970-01-01
      • 2021-08-01
      • 1970-01-01
      • 2015-01-10
      • 1970-01-01
      • 1970-01-01
      • 2011-03-14
      相关资源
      最近更新 更多