web-dev-qa-db-fra.com

Func vs. Action vs. Prédicat

Avec des exemples réels et leur utilisation, quelqu'un peut-il m'aider à comprendre:

  1. Quand avons-nous besoin d'un délégué Func?
  2. Quand avons-nous besoin d'un délégué d'action?
  3. Quand avons-nous besoin d'un délégué aux prédicats?
690
InfoLearner

La différence entre Func et Action consiste simplement à demander au délégué de renvoyer une valeur (utilisez Func) ou non (utilisez Action).

Func est probablement le plus couramment utilisé dans LINQ - par exemple dans les projections:

 list.Select(x => x.SomeProperty)

ou filtrer:

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

ou sélection de clé:

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

Action est plus couramment utilisé pour des opérations telles que List<T>.ForEach: exécute l'action indiquée pour chaque élément de la liste. J'utilise ceci moins souvent que Func, bien que je do utilise parfois la version sans paramètre pour des choses comme Control.BeginInvoke et Dispatcher.BeginInvoke.

Predicate n'est qu'un cas particulier Func<T, bool> réellement introduit avant tous les Func et la plupart des délégués Action. Je suppose que si nous avions déjà eu Func et Action sous leurs différentes formes, Predicate n'aurait pas été introduit ... bien que cela soit fait donne un certain sens à l'utilisation du délégué, alors que Func et Action sont utilisés à des fins très différentes.

Predicate est principalement utilisé dans List<T> pour des méthodes telles que FindAll et RemoveAll.

869
Jon Skeet

Action est un délégué (pointeur) à une méthode, qui prend zéro, un ou plusieurs paramètres d'entrée, mais ne renvoie rien.

Func est un délégué (pointeur) à une méthode, qui prend zéro, un ou plusieurs paramètres d'entrée et renvoie une valeur (ou une référence).

Predicate est un type spécial de Func souvent utilisé pour les comparaisons.

Bien que largement utilisés avec Linq, Action et Func sont des concepts logiquement indépendants de Linq. C++ contenait déjà le concept de base sous la forme de pointeurs de fonctions typés.

Voici un petit exemple pour Action et Func sans utiliser 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;
    }
}
344
Knasterbax

Func - Lorsque vous souhaitez un délégué pour une fonction pouvant ou non prendre des paramètres et renvoyer une valeur. L’exemple le plus courant serait Select from LINQ:

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

Action - Lorsque vous souhaitez un délégué pour une fonction pouvant ou non prendre des paramètres et ne pas renvoyer de valeur. J'utilise souvent ces gestionnaires d'événements anonymes:

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

Prédicat - Lorsque vous voulez une version spécialisée d'un Func qui évalue une valeur par rapport à un ensemble de critères et renvoie un résultat booléen (true pour une correspondance, false sinon). Encore une fois, LINQ les utilise fréquemment pour des tâches telles que Où:

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

Je viens de vérifier et il s'avère que LINQ n'utilise pas de prédicats. Vous ne savez pas pourquoi ils ont pris cette décision… mais théoriquement, c'est toujours un cas où un prédicat conviendrait.

64
Justin Niessner