Func vs Action vs Prédicat

Func vs Action vs Prédicat

La différence entre Func et Action est simplement si vous voulez que le délégué renvoie 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 filtrage :

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

ou sélection de touche :

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

Action est plus couramment utilisé pour des choses comme List<T>.ForEach :exécute l'action donnée pour chaque élément de la liste. Je l'utilise moins souvent que Func , même si je fais utilise parfois la version sans paramètre pour des choses comme Control.BeginInvoke et Dispatcher.BeginInvoke .

Predicate est juste un Func<T, bool> avec une casse spéciale vraiment, présenté avant tous les Func et la plupart des Action les délégués sont arrivés. Je soupçonne que si nous avions déjà eu Func et Action sous leurs différentes formes, Predicate n'aurait pas été introduit... bien qu'il le fasse donner un certain sens à l'utilisation du délégué, alors que Func et Action sont utilisés à des fins très disparates.

Predicate est principalement utilisé dans List<T> pour les méthodes comme FindAll et RemoveAll .


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

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

Prédicat 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 fonction 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;
    }
}

Fonction - Lorsque vous voulez un délégué pour une fonction qui peut ou non prendre des paramètres et retourner une valeur. L'exemple le plus courant serait Select from LINQ :

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

Action - Lorsque vous voulez un délégué pour une fonction qui peut ou non prendre des paramètres et ne renvoie pas de valeur. Je les utilise souvent pour les gestionnaires d'événements anonymes :

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

Prédicat - Lorsque vous souhaitez 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, ceux-ci sont utilisés assez fréquemment dans LINQ pour des choses comme Where :

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. Je ne sais pas pourquoi ils ont pris cette décision... mais théoriquement, c'est toujours une situation où un prédicat conviendrait.