C# 中的谓词是什么?

发布于 2024-08-10 05:57:30 字数 141 浏览 3 评论 0原文

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

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

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

I am very new to using predicates and just learned how to write:

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

What will the predicate return, and how is it useful when programming?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梦里人 2024-08-17 05:57:30

Predicate 是一个函数式构造,提供了一种方便的方法来基本测试给定 T 对象的某些内容是否为真。

例如,假设我有一个类:

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

现在假设我有一个 List;人们,我想知道名单中是否有名为奥斯卡的人。

如果不使用 Predicate(或 Linq,或任何其他奇特的东西),我总是可以通过执行以下操作来完成此操作:

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

if (oscar != null) {
    // Oscar exists!
}

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

使用谓词,我可以使用更少的代码找到这些东西:

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

注意我说的是更少的代码,而不是更快 >。开发人员的一个常见误解是,如果某个东西只需要一行,那么它的性能一定比需要十行的东西要好。但在幕后,采用 PredicateFind 方法毕竟只是枚举。 Linq 的许多功能也是如此。

那么让我们看一下您问题中的具体代码:

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

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

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

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

int firstEven = ints.Find(pre);

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

int firstEven = ints.Find(evenFinder);

Predicate<T> is a functional construct providing a convenient way of basically testing if something is true of a given T object.

For example suppose I have a class:

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

Now let's say I have a List<Person> people and I want to know if there's anyone named Oscar in the list.

Without using a Predicate<Person> (or Linq, or any of that fancy stuff), I could always accomplish this by doing the following:

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

if (oscar != null) {
    // Oscar exists!
}

This is fine, but then let's say I want to check if there's a person named "Ruth"? Or a person whose age is 17?

Using a Predicate<Person>, I can find these things using a LOT less code:

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

Notice I said a lot less code, not a lot faster. A common misconception developers have is that if something takes one line, it must perform better than something that takes ten lines. But behind the scenes, the Find method, which takes a Predicate<T>, is just enumerating after all. The same is true for a lot of Linq's functionality.

So let's take a look at the specific code in your question:

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

Here we have a Predicate<int> pre that takes an int a and returns a % 2 == 0. This is essentially testing for an even number. What that means is:

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

And so on. This also means, if you have a List<int> ints and you want to find the first even number, you can just do this:

int firstEven = ints.Find(pre);

Of course, as with any other type that you can use in code, it's a good idea to give your variables descriptive names; so I would advise changing the above pre to something like evenFinder or isEven -- something along those lines. Then the above code is a lot clearer:

int firstEven = ints.Find(evenFinder);
鹿港小镇 2024-08-17 05:57:30

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

Predicate基本上与Func

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

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

The Predicate will always return a boolean, by definition.

Predicate<T> is basically identical to Func<T,bool>.

Predicates are very useful in programming. They are often used to allow you to provide logic at runtime, that can be as simple or as complicated as necessary.

For example, WPF uses a Predicate<T> as input for Filtering of a ListView's ICollectionView. This lets you write logic that can return a boolean determining whether a specific element should be included in the final view. The logic can be very simple (just return a boolean on the object) or very complex, all up to you.

相守太难 2024-08-17 05:57:30

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

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

The following code can help you to understand some real world use of predicates (Combined with named iterators).

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;
        }
    }
}
萝莉病 2024-08-17 05:57:30

在 C# 中,谓词只是返回布尔值的委托。当您搜索对象集合并想要特定的内容时,它们非常有用(根据我的经验)。

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

In C# Predicates are simply delegates that return booleans. They're useful (in my experience) when you're searching through a collection of objects and want something specific.

I've recently run into them in using 3rd party web controls (like treeviews) so when I need to find a node within a tree, I use the .Find() method and pass a predicate that will return the specific node I'm looking for. In your example, if 'a' mod 2 is 0, the delegate will return true. Granted, when I'm looking for a node in a treeview, I compare it's name, text and value properties for a match. When the delegate finds a match, it returns the specific node I was looking for.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文