Func vs. Acción vs. Predicado

Con ejemplos reales y su uso, alguien puede ayudarme a entender:

  1. ¿Cuándo necesitamos el delegado de Func?
  2. ¿Cuándo necesitamos el delegado de Acción?
  3. ¿Cuándo necesitamos el delegado Predicates?

La diferencia entre Func y Action es simplemente si desea que el delegado devuelva un valor (use Func ) o no (use Action ).

Func es probablemente el más comúnmente utilizado en LINQ, por ejemplo en proyecciones:

  list.Select(x => x.SomeProperty) 

o filtrado:

  list.Where(x => x.SomeValue == someOtherValue) 

o la selección de la clave:

  list.Join(otherList, x => x.FirstKey, y => y.SecondKey, ...) 

Action se usa más comúnmente para cosas como List.ForEach : ejecuta la acción dada para cada elemento en la lista. Lo uso con menos frecuencia que Func , aunque a veces uso la versión sin parámetros para cosas como Control.BeginInvoke y Dispatcher.BeginInvoke .

Predicate es solo un Func realmente presentado, presentado antes de todos los Func y la mayoría de los delegates de Action se presentaron. Sospecho que si ya hubiéramos tenido Func y Action en sus diversas apariencias, Predicate no se habría introducido … aunque sí da un cierto significado al uso del delegado, mientras que Func y Action se usan para disparar ampliamente propósitos.

Predicate se usa principalmente en List para métodos como FindAll y RemoveAll .

La acción es un delegado (puntero) a un método, que toma cero, uno o más parámetros de entrada, pero no devuelve nada.

Func es un delegado (puntero) para un método, que toma cero, uno o más parámetros de entrada y devuelve un valor (o referencia).

Predicate es un tipo especial de Func que se usa a menudo para realizar comparaciones.

Aunque ampliamente utilizado con Linq, Action y Func son conceptos lógicamente independientes de Linq. C ++ ya contenía el concepto básico en forma de punteros de función tipeados.

Aquí hay un pequeño ejemplo para Action y Func sin usar Linq:

 class Program { static void Main(string[] args) { Action myAction = new Action(DoSomething); myAction(123); // Prints out "123" // can be also called as myAction.Invoke(123); Func myFunc = new Func(CalculateSomething); Console.WriteLine(myFunc(5)); // Prints out "2.5" } static void DoSomething(int i) { Console.WriteLine(i); } static double CalculateSomething(int i) { return (double)i/2; } } 

Func : cuando desea un delegado para una función que puede o no tomar parámetros y devolver un valor. El ejemplo más común sería Seleccionar de LINQ:

 var result = someCollection.Select( x => new { x.Name, x.Address }); 

Acción : cuando quiere un delegado para una función que puede o no tomar parámetros y no devuelve un valor. Los uso a menudo para manejadores de eventos anónimos:

 button1.Click += (sender, e) => { /* Do Some Work */ } 

Predicado : cuando desea una versión especializada de un Func que evalúa un valor contra un conjunto de criterios y devuelve un resultado booleano (verdadero para una coincidencia, falso en caso contrario). De nuevo, estos se usan en LINQ con bastante frecuencia para cosas como Where:

 var filteredResults = someCollection.Where(x => x.someCriteriaHolder == someCriteria); 

Lo comprobé dos veces y resulta que LINQ no usa Predicates. No estoy seguro de por qué tomaron esa decisión … pero, en teoría, todavía es una situación en la que cabría un Predicado.