2010-11-30 19 views
576

con ejemplos reales y su uso, por favor alguien puede ayudarme a entender:Func vs Acción contra predicado

  1. ¿Cuándo necesitamos Func delegado?
  2. ¿Cuándo necesitamos la acción delegar?
  3. ¿Cuándo necesitamos un delegado de Predicados?
+2

pesar de que este es un duplicado tiene una respuesta aceptada más a fondo – reggaeguitar

+4

@reggaeguitar Lo que es interesante es que tanto de la respuesta aceptada es de Jon Skeet – rafid059

Respuesta

743

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

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

list.Select(x => x.SomeProperty) 

o filtrado:

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

o tecla de selección:

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

Action es más comúnmente utilizado para cosas como : ejecutar el dar n acción para cada elemento en la lista. Lo uso con menos frecuencia que Func, aunque I do a veces usa la versión sin parámetros para cosas como Control.BeginInvoke y Dispatcher.BeginInvoke.

Predicate es realmente una carcasa especial Func<T, bool> realmente, presentada antes de todos los Func y la mayoría de los delegados Action llegaron. Sospecho que si ya habíamos tenido Func y Action en sus diversas formas, Predicate no se hubieran introducido ... aunque no impartir un cierto significado para el uso del delegado, mientras que Func y Action se utilizan para propósitos ampliamente dispares.

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

+50

Me gusta mucho ver 'Predicado' en una firma de función. Ilustra que el método pasado toma una decisión en lugar de solo devolver un código de éxito o un tipo diferente de 'bool'. –

+5

¿Hay alguna directriz de diseño sobre si prefiere 'Predicado ' o 'Func '? Me gusta la expresividad de 'Predicate', pero también he visto recomendaciones para' Func'. – CodesInChaos

+3

@Ron: Sí, de eso se trata mi penúltimo párrafo. –

55

Func - Cuando quiere 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 se desea un delegado para una función que pueden o no tener parámetros y no devuelve un valor. Yo uso estos a menudo para los controladores de eventos anónimos:

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

predicado - Cuando se desea una versión especializada de un Func que toma evalúa un valor contra un conjunto de criterios y devuelve un resultado booleano (verdadero para un partido, falso de lo contrario). Una vez más, estos se utilizan en LINQ con bastante frecuencia para cosas como Dónde:

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

acabo comprobados con minuciosidad y resulta que LINQ no utiliza predicados. 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.

+2

Sé que esto es antiguo, pero LINK no utilizó Predicate porque es anterior al Func y a la Acción que conocemos hoy, y los dos últimos se pueden usar para obtener exactamente el mismo resultado de una manera mucho mejor. – gparent

+0

@gparent, ¿por qué es mejor? Creo que la legibilidad es mejor cuando se usan delegados con nombres significativos en lugar de 'Func' o' Action'. – Sam

+1

Depende de cómo use los delegados, pero a veces el nombre no es tan importante y tener que crear funciones y variables para un solo uso me disminuye la legibilidad. – gparent

287

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

Predicado es un tipo especial de Func de uso frecuente para las 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 la Acción y Func sin utilizar 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; 
    } 
} 
+20

Predicado es un delegado que toma los parámetros genéricos y devuelve bool – Martin

+24

¡Buen ejemplo! Tenga en cuenta que también puede invocar myAction llamándolo simplemente: 'myAction (123);'. No necesita usar '.Invoke()' – romar

Cuestiones relacionadas