Что такое предикат в С#?

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

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

Как будет возвращаться предикат и как он полезен при программировании?

Ответ 1

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

Это хорошо, но потом скажите, я хочу проверить, есть ли человек по имени "Рут"? Или человек, возраст которого составляет 17 лет?

Используя Predicate<Person>, я могу найти эти вещи, используя код LOT less:

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

Ответ 2

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

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

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

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

Ответ 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;
        }
    }
}

Ответ 4

В С# Predicates - это просто делегаты, которые возвращают логические значения. Они полезны (по моему опыту), когда вы просматриваете коллекцию объектов и хотите что-то конкретное.

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