Я очень новичок в использовании предикатов и просто научился писать:
Predicate<int> pre = delegate(int a){ a %2 == 0 };
Как будет возвращаться предикат и как он полезен при программировании?
Я очень новичок в использовании предикатов и просто научился писать:
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!
}
Это хорошо, но потом скажите, я хочу проверить, есть ли человек по имени "Рут"? Или человек, возраст которого составляет 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);
Предикат всегда будет возвращать логическое значение по определению.
Predicate<T>
в основном идентичен Func<T,bool>
.
Предикаты очень полезны при программировании. Они часто используются для обеспечения логики во время выполнения, которая может быть как простой, так и сложной, если это необходимо.
Например, WPF использует Predicate<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;
}
}
}
В С# Predicates - это просто делегаты, которые возвращают логические значения. Они полезны (по моему опыту), когда вы просматриваете коллекцию объектов и хотите что-то конкретное.
Недавно я столкнулся с ними в использовании сторонних веб-элементов управления (например, treeviews), поэтому, когда мне нужно найти node внутри дерева, я использую метод .Find() и передаю предикат, который вернет специфический node Я ищу. В вашем примере, если 'a' mod 2 равен 0, делегат вернет true. Конечно, когда я ищу node в дереве, я сравниваю его свойства имени, текста и значения для соответствия. Когда делегат находит совпадение, он возвращает конкретный node, который я искал.