Delegaci: predykat vs. akcja vs. funkcja

137

Czy ktoś może podać dobre wyjaśnienie (miejmy nadzieję, przykłady) tych 3 najważniejszych delegatów:

  • Orzec
  • Akcja
  • Func
Andrzej
źródło

Odpowiedzi:

180
  • Predicate: zasadniczo Func<T, bool>; zadaje pytanie „czy określony argument spełnia warunek reprezentowany przez delegata?” Używane w takich rzeczach, jak List.FindAll.

  • Action: Wykonuje akcję, podając argumenty. Bardzo ogólny cel. Niewiele używany w LINQ, ponieważ zasadniczo oznacza to efekty uboczne.

  • Func: Używany szeroko w LINQ, zwykle do transformacji argumentu, np. Poprzez rzutowanie złożonej struktury na jedną właściwość.

Inni ważni delegaci:

  • EventHandler/ EventHandler<T>: Używany we wszystkich WinForms

  • Comparison<T>: Jak, IComparer<T>ale w formie delegata.

Jon Skeet
źródło
3
Jest też System.Converter<TInput, TOutput>, choć rzadko jest używany.
G-Wiz
4
Konwerter jest miłym delegatem, gdy potrzeba dużo konwersji modelu na klasy biznesowe, np. Stum.de/2009/12/23/ ...
Michael Stum
EventHandler/EventHandler<T>pojawiają się wszędzie poza WinForms.
Andy
@Andy: Trochę ... Ale mniej na przykład w WPF. Zgadzam się, że nie ma nic specyficznego dla WinForms.
Jon Skeet
48

Action, FuncA Predicatewszystkie należą do rodziny delegata.

Action : Akcja może przyjąć n parametrów wejściowych, ale zwraca void.

Func: Func może przyjąć n parametrów wejściowych, ale zawsze zwróci wynik podanego typu. Func<T1,T2,T3,TResult>, tutaj T1, T2, T3 są parametrami wejściowymi, a TResult jest ich wynikiem.

Predicate: Predicate jest również formą Func, ale zawsze zwraca wartość bool. W prostych słowach jest to opakowanie Func<T,bool>.

Rahul Garg
źródło
NAJLEPSZA i NAJPROSTSZA odpowiedź, jaką kiedykolwiek znalazłem w odniesieniu do tego pytania
Reyan Chougle
@ReyanChougle: Cieszę się, że jest to pomocne.
Rahul Garg
9

Oprócz odpowiedzi Jona jest też

  • Converter<TInput, TOutput>: Zasadniczo Func<TInput, TOutput>, ale z semantyką. Używany przez List.ConvertAll i Array.ConvertAll, ale osobiście nie widziałem go nigdzie indziej.
G-Wiz
źródło
4

MethodInvoker to metoda, z której mogą korzystać programiści WinForms; nie przyjmuje żadnych argumentów i nie zwraca żadnych wyników. Poprzedza Action i nadal jest często używany podczas wywoływania wątku interfejsu użytkownika, ponieważ BeginInvoke () i inni akceptują delegata bez typu; chociaż Action będzie równie dobrze.

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

Byłbym również świadomy ThreadStart i ParameterizedThreadStart; znowu większość ludzi w dzisiejszych czasach zastąpi Akcję.

El Zorko
źródło
3

Predicate, Func i Action to wbudowane wystąpienia delegatów platformy .NET. Każde z tych wystąpień delegatów może odwoływać się lub wskazywać na metody użytkownika z określonym podpisem.

Delegat akcji - wystąpienia delegata akcji mogą wskazywać metody, które pobierają argumenty i zwracają void.

Delegat Func - wystąpienie delegata Func może wskazywać metody, które pobierają zmienną liczbę argumentów i zwracają określony typ.

Predykaty - predykaty są podobne do instancji delegatów func i mogą wskazywać metody, które pobierają zmienną liczbę argumentów i zwracają typ bool.

IntelligentBinary
źródło
2

Action and Func z 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();
Ostry ból
źródło
2

Func jest bardziej przyjazny dla LINQ, można go przekazać jako parametr. (bez punktów)

Predykatu nie można, trzeba ponownie opakować.

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
źródło
2

Prosty przykład o argumentach i powtórzeniach każdego typu

Ta Func pobiera dwa argumenty int i zwraca int.Func zawsze zwraca typ

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

W tym przypadku func nie ma argumentów, ale zwraca łańcuch

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

Ta akcja przyjmuje dwa argumenty int i zwraca 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

Ten predykat przyjmuje jeden argument i zawsze zwraca wartość bool. Ogólnie rzecz biorąc, predykaty zawsze zwracają wartość bool.

Predicate<int> isPositive = (x) => x > 0;
Console.WriteLine(isPositive(5));//Print True
dimath
źródło