Может ли кто-нибудь дать хорошее объяснение (надеюсь, с примерами) этих 3 наиболее важных делегатов:
- Предикат
- Действие
- Func
О чем другие делегаты должны знать разработчики С#?
Как часто вы используете их в производственном коде?
Может ли кто-нибудь дать хорошее объяснение (надеюсь, с примерами) этих 3 наиболее важных делегатов:
О чем другие делегаты должны знать разработчики С#?
Как часто вы используете их в производственном коде?
Predicate
: по существу Func<T, bool>
; задает вопрос: "соответствует ли указанный аргумент условию, представленному делегатом?" Используется в таких вещах, как List.FindAll.
Action
: выполнить действие с аргументами. Очень общая цель. Не используется много в LINQ, поскольку это подразумевает побочные эффекты, в основном.
Func
: широко используется в LINQ, как правило, для преобразования аргумента, например. проецируя сложную структуру на одно свойство.
Другие важные делегаты:
EventHandler
/EventHandler<T>
: используется во всех WinForms
Comparison<T>
: Как IComparer<T>
, но в форме делегата.
Action
, Func
и Predicate
принадлежат семье делегатов.
Action
: Действие может принимать n входных параметров, но возвращает void.
Func
: Func может принимать n входных параметров, но он всегда будет возвращать результат указанного типа. Func<T1,T2,T3,TResult>
, здесь T1, T2, T3 - входные параметры, а TResult - его выход.
Predicate
: Предикат также является формой Func, но он всегда возвращает bool. Проще говоря, это оболочка Func<T,bool>
.
В дополнение к ответу Jon, есть также
Converter<TInput, TOutput>
: По существу Func<TInput, TOutput>
, но с семантикой. Используются List.ConvertAll и Array.ConvertAll, но лично их больше не видели.MethodInvoker - это тот, который разработчики WinForms могут использовать; он не принимает аргументов и не возвращает никаких результатов. Он предшествует Action и по-прежнему часто используется при вызове в поток пользовательского интерфейса, поскольку BeginInvoke() и другие принимают нетипизированный делегат; хотя действие будет так же хорошо.
myForm.BeginInvoke((MethodInvoker)delegate
{
MessageBox.Show("Hello, world...");
});
Я бы также знал о ThreadStart и ParameterizedThreadStart; снова большинство людей заменит действие в наши дни.
Predicate, Func и Action - встроенные экземпляры делегатов .NET. Каждый из этих экземпляров делегата может ссылаться или указывать на пользовательские методы с определенной сигнатурой.
Делегатор действий - экземпляры делегирования действий могут указывать на методы, которые принимают аргументы и возвращают void.
Делитель Func - экземпляр делегата Func может указывать на метод (ы), который принимает переменное количество аргументов и возвращает некоторый тип.
Предикат - Предикаты похожи на экземпляры делегатов func, и они могут указывать на методы, которые принимают переменное количество аргументов и возвращают тип bool.
Действие и Func с lambda:
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();
Другие уже упоминали правильное использование конкретных делегатов, но я хотел бы добавить что-то, что завершит их ответы. Имена Func, Action, Predicate имеют математический фон. Чтобы все было просто, я дам неформальное определение математической функции:
Функция - это взаимосвязь между множествами. Мы берем член одного набора и используем его как вход, и функция отображает этот вход только на один член другого набора. Другими словами, что-то вводит и выводит результат.
Опять же, неофициально, математический предикат - это утверждение, которое может быть истинным или ложным в зависимости от его переменных. Как и другие, упоминается функция, которая возвращает логическое значение.
И последнее: Action - это функция void (или более математически корректное имя - метод или процедура)
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
Простой пример об аргументах и о том, что возвращает каждый тип
Этот 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