Делегаты: Предикат против Действия против Функ

137

Может ли кто-нибудь дать хорошее объяснение (надеюсь, с примерами) этих 3 самых важных делегатов:

  • сказуемое
  • действие
  • Func
Андрей
источник

Ответы:

180
  • Predicateпо существу Func<T, bool>; задает вопрос "удовлетворяет ли указанный аргумент условию, представленному делегатом?" Используется в таких вещах, как List.FindAll.

  • Action: Выполнить действие с учетом аргументов. Очень общее назначение. В LINQ мало используется, так как в основном это подразумевает побочные эффекты.

  • Func: Широко используется в LINQ, обычно для преобразования аргумента, например, путем проекции сложной структуры на одно свойство.

Другие важные делегаты:

  • EventHandler/ EventHandler<T>: Используется во всех WinForms

  • Comparison<T>Как IComparer<T>в делегатской форме.

Джон Скит
источник
3
Там также System.Converter<TInput, TOutput>, хотя это редко используется.
G-Wiz
4
Преобразователь хороший делегат , когда много Конвертирования модели в бизнес - классы требуются, т.е. stum.de/2009/12/23/...
Майкл Stum
EventHandler/EventHandler<T>появляются повсюду за пределами WinForms тоже.
Энди
@Анди: В некоторой степени ... Но в WPF меньше, например. Я согласен, что нет ничего специфичного для WinForms.
Джон Скит
48

Action, FuncИ Predicateвсе они принадлежат к семейству делегата.

Action : Действие может принимать n входных параметров, но возвращает void.

Func: Func может принимать n входных параметров, но всегда будет возвращать результат указанного типа. Func<T1,T2,T3,TResult>здесь T1, T2, T3 - входные параметры, а TResult - его выходные данные.

PredicateПредикат также является формой Func, но он всегда возвращает bool. Простыми словами это обертка Func<T,bool>.

Рахул Гарг
источник
ЛУЧШИЙ и ПРОСТОЙ ответ, который я когда-либо нашел в отношении этого вопроса
Рейан Чоугл
@ReyanChougle: Рад, что вы находите это полезным.
Рахул
9

В дополнение к ответу Джона, есть также

  • Converter<TInput, TOutput>: По сути Func<TInput, TOutput>, но с семантикой. Используется List.ConvertAll и Array.ConvertAll, но лично я его больше нигде не видел.
G-Wiz
источник
4

MethodInvoker - это метод, который могут использовать разработчики WinForms; он не принимает аргументов и не возвращает результатов. Он предшествует действию и до сих пор часто используется при вызове в потоке пользовательского интерфейса, поскольку BeginInvoke () и другие принимают нетипизированный делегат; хотя Действие будет так же хорошо.

myForm.BeginInvoke((MethodInvoker)delegate
{
  MessageBox.Show("Hello, world...");
});

Я также знал бы о ThreadStart и ParameterizedThreadStart; снова большинство людей заменит действие в эти дни.

Эль Зорко
источник
3

Predicate, Func и Action являются встроенными экземплярами делегатов .NET. Каждый из этих экземпляров делегата может ссылаться или указывать на пользовательские методы с определенной сигнатурой.

Делегат действия - экземпляры делегата действия могут указывать на методы, которые принимают аргументы и возвращают void.

Делегат Func - экземпляр делегата Func может указывать на метод (ы), которые принимают переменное число аргументов и возвращают некоторый тип.

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

IntelligentBinary
источник
2

Действие и функционал с лямбдой:

person p = new person();
Action<int, int> mydel = p.add;       /*(int a, int b) => { Console.WriteLine(a + b); };*/
Func<string, string> mydel1 = p.conc; /*(string s) => { return "hello" + s; };*/
mydel(2, 3);
string s1=  mydel1(" Akhil");
Console.WriteLine(s1);
Console.ReadLine();
острая боль
источник
2

Func более дружественен по отношению к LINQ, его можно передавать как параметр. (Точка-бесплатно)

Предикат не может, должен быть снова упакован.

Predicate<int> IsPositivePred = i => i > 0;
Func<int,bool> IsPositiveFunc = i => i > 0;

new []{2,-4}.Where(i=>IsPositivePred(i)); //Wrap again

new []{2,-4}.Where(IsPositivePred);  //Compile Error
new []{2,-4}.Where(IsPositiveFunc);  //Func as Parameter
Rm558
источник
2

Простой пример об аргументах и ​​о том, что возвращает каждый тип

Этот Func принимает два аргумента int и возвращает int.Func всегда имеет возвращаемый тип

 Func<int, int, int> sum = (a, b) => a + b;
 Console.WriteLine(sum(3, 5));//Print 8

В этом случае func не имеет аргументов, но возвращает строку

Func<string> print = () => "Hello world";
Console.WriteLine(print());//Print Hello world

Это действие принимает два аргумента int и возвращает void

Action<int, int> displayInput = (x, y) => Console.WriteLine("First number is :" + x + " , Second number is "+ y);
displayInput(4, 6); //Print First number is :4 , Second number is :6

Этот предикат принимает один аргумент и всегда возвращает bool. Обычно предикаты всегда возвращают bool.

Predicate<int> isPositive = (x) => x > 0;
Console.WriteLine(isPositive(5));//Print True
dimath
источник