Вопрос

На этот вопрос уже есть ответ здесь:

Я очень новичок в использовании предикатов и только что научился писать:

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 и я хочу знать, есть ли в списке кто-нибудь по имени Оскар.

Без используя 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);

Заметьте, я сказал очень много меньше кода, не так уж много быстрее.Распространенное заблуждение разработчиков заключается в том, что если что-то занимает одну строку, оно должно работать лучше, чем то, что занимает десять строк.Но за кулисами, в Find метод, который требует Predicate<T>, в конце концов, это просто перечисление.То же самое верно и для многих функциональных возможностей 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);

Другие советы

По определению, предикат всегда будет возвращать логическое значение.

Predicate<T> в основном идентичен Func<T,bool>.

Предикаты очень полезны в программировании.Они часто используются, чтобы позволить вам предоставить логику во время выполнения, которая может быть настолько простой или настолько сложной, насколько это необходимо.

Например, WPF использует Predicate<T> в качестве входных данных для фильтрации ICollectionView в ListView.Это позволяет вам написать логику, которая может возвращать логическое значение, определяющее, следует ли включать определенный элемент в итоговое представление.Логика может быть очень простой (просто возвращайте логическое значение для объекта) или очень сложной, все зависит от вас.

Следующий код может помочь вам понять некоторое реальное использование предикатов (в сочетании с именованными итераторами).

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 # предикаты - это просто делегаты, которые возвращают логические значения.Они полезны (по моему опыту), когда вы просматриваете коллекцию объектов и хотите что-то конкретное.

Недавно я столкнулся с ними при использовании сторонних веб-элементов управления (например, treeviews), поэтому, когда мне нужно найти узел в дереве, я использую .Метод Find() и передаю предикат, который вернет конкретный узел, который я ищу.В вашем примере, если 'a' mod 2 равно 0, делегат вернет true .Конечно, когда я ищу узел в treeview, я сравниваю его свойства name, text и value на предмет совпадения.Когда делегат находит совпадение, он возвращает конкретный узел, который я искал.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top