Delegados: Predicado vs. Acción vs. Func.

137

¿Puede alguien proporcionar una buena explicación (con suerte con ejemplos) de estos 3 delegados más importantes:

  • Predicado
  • Acción
  • Func
Andrés
fuente

Respuestas:

180
  • Predicate: esencialmente Func<T, bool>; hace la pregunta "¿satisface el argumento especificado la condición representada por el delegado?" Usado en cosas como List.FindAll.

  • Action: Realiza una acción dados los argumentos. Propósito muy general. No se usa mucho en LINQ ya que implica efectos secundarios, básicamente.

  • Func: Se usa ampliamente en LINQ, generalmente para transformar el argumento, por ejemplo, proyectando una estructura compleja en una propiedad.

Otros delegados importantes:

  • EventHandler/ EventHandler<T>: Utilizado en todos los WinForms

  • Comparison<T>: Me gusta IComparer<T>pero en forma de delegado.

Jon Skeet
fuente
3
También hay System.Converter<TInput, TOutput>, aunque rara vez se usa.
G-Wiz
44
El convertidor es un buen delegado cuando se necesita mucha conversión de modelo en clases de negocios, es decir, stum.de/2009/12/23/…
Michael Stum
EventHandler/EventHandler<T>aparecer por todas partes fuera de WinForms también.
Andy
@Andy: Algo ... Pero menos en WPF, por ejemplo. Estoy de acuerdo en que no hay nada específico de WinForms.
Jon Skeet
48

Action, Funcy Predicatetodos pertenecen a la familia delegada.

Action : La acción puede tomar n parámetros de entrada pero devuelve nulo.

Func: Func puede tomar n parámetros de entrada pero siempre devolverá el resultado del tipo proporcionado. Func<T1,T2,T3,TResult>, aquí T1, T2, T3 son parámetros de entrada y TResult es la salida del mismo.

Predicate: Predicate también es una forma de Func pero siempre devolverá bool. En palabras simples es envoltorio de Func<T,bool>.

Rahul Garg
fuente
La mejor y más simple respuesta que he encontrado con respecto a esta pregunta
Reyan Chougle
@ReyanChougle: Me alegro, te resulta útil.
Rahul Garg el
9

Además de la respuesta de Jon, también hay

  • Converter<TInput, TOutput>: Es esencialmente Func<TInput, TOutput>, pero con semántica. Usado por List.ConvertAll y Array.ConvertAll, pero personalmente no lo he visto en ningún otro lado.
G-Wiz
fuente
4

MethodInvoker es uno que los desarrolladores de WinForms pueden usar; no acepta argumentos y no devuelve resultados. Es anterior a Action, y todavía se usa a menudo cuando se invoca en el hilo de la interfaz de usuario, ya que BeginInvoke () y otros aceptan un delegado sin tipo; aunque la acción funcionará igual de bien.

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

También estaría al tanto de ThreadStart y ParameterizedThreadStart; nuevamente, la mayoría de las personas sustituirá una Acción en estos días.

El Zorko
fuente
3

Predicate, Func y Action son instancias de delegado incorporadas de .NET. Cada una de estas instancias de delegado podría referirse o señalar métodos de usuario con firma específica.

Delegado de acción: las instancias de delegado de acción pueden apuntar a métodos que toman argumentos y devuelven nulo.

Delegado de Func: la instancia de delegado de Func podría apuntar a métodos que toman un número variable de argumentos y devuelven algún tipo.

Predicate: los predicados son similares a las instancias de delegado de funciones y pueden apuntar a métodos que toman un número variable de argumentos y devuelven un tipo bool.

Binario inteligente
fuente
2

Acción y Func con 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();
Angustia
fuente
2

Func es más compatible con LINQ, se puede pasar como parámetro. (sin puntos)

El predicado no puede, tiene que ser envuelto nuevamente.

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
fuente
2

Un ejemplo simple sobre los argumentos y lo que retutn cada tipo

Este Func toma dos argumentos int y devuelve un int.Func siempre tiene un tipo de retorno

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

En este caso, func no tiene argumentos pero devuelve una cadena

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

Esta acción toma dos argumentos int y devuelve nulo

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

Este predicado toma un argumento y siempre devuelve bool. Generalmente, los predicados siempre devuelven bool.

Predicate<int> isPositive = (x) => x > 0;
Console.WriteLine(isPositive(5));//Print True
dimath
fuente