Func frente de Acción frente Predicado [duplicate]


Esta pregunta ya tiene una respuesta aquí:

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

  1. ¿Cuándo necesitamos un delegado Func?
  2. ¿Cuándo necesitamos delegado de acción?
  3. ¿Cuándo necesitamos delegar Predicados?
 620
Author: Reese Moore, 2010-11-30

3 answers

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 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 selección de teclas:

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

Action se usa más comúnmente para cosas como List<T>.ForEach: ejecutar la acción dada para cada elemento de la lista. Uso esto con menos frecuencia que Func, aunque hago a veces uso el versión sin parámetros para cosas como Control.BeginInvoke y Dispatcher.BeginInvoke.

Predicate es solo un caso especial Func<T, bool> realmente, presentado antes de todos los Func y la mayoría de los Action delegados vinieron. Sospecho que si ya hubiéramos tenido Func y Action en sus diversas formas, Predicate no se habrían introducido... aunque hace impartir un cierto significado al uso del delegado, mientras que Func y Action se utilizan para fines muy dispares.

Predicate se utiliza sobre todo en List<T> para métodos como FindAll y RemoveAll.

 792
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-14 03:55:15

Action 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) a un método, que toma cero, uno o más parámetros de entrada, y devuelve un valor (o referencia).

El predicado es un tipo especial de Func usado a menudo para comparaciones.

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

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

class Program
{
    static void Main(string[] args)
    {
        Action<int> myAction = new Action<int>(DoSomething);
        myAction(123);           // Prints out "123"
                                 // can be also called as myAction.Invoke(123);

        Func<int, double> myFunc = new Func<int, double>(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;
    }
}
 314
Author: Knasterbax,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-08 21:04:16

Func - Cuando desea un delegado para una función que puede o no tomar parámetros y devuelve un valor. El ejemplo más común sería Select from LINQ:

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

Action - Cuando desea 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 */ }

Predicate - Cuando desea una versión especializada de un Func que evalúa un valor contra un conjunto de criterios y devuelve un resultado booleano (true para una coincidencia, false de lo contrario). Nuevamente, estos se usan en LINQ con bastante frecuencia para cosas como Where:

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

Acabo de comprobar dos veces y resulta que LINQ no utiliza Predicados. No estoy seguro de por qué tomaron esa decisión...pero teóricamente todavía es una situación donde un Predicado encajaría.

 57
Author: Justin Niessner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-25 11:17:39