823 votes

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 Func<T, ..> délégué ?
  2. Quand avons-nous besoin d'un Action<T> délégué ?
  3. Quand avons-nous besoin d'un Predicate<T> délégué ?

10 votes

Même s'il s'agit d'un doublon, la réponse acceptée est plus complète.

10 votes

Ce qui est intéressant, c'est que les deux réponses acceptées sont celles de Jon Skeet.

2 votes

La lecture du livre de Jon Skeet, C# in Depth, m'a amené ici. Tu parles d'un début.

1027voto

Jon Skeet Points 692016

La différence entre Func y Action est simplement de savoir si vous voulez que le délégué retourne une valeur (utiliser Func ) ou non (utiliser Action ).

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

 list.Select(x => x.SomeProperty)

ou le filtrage :

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

ou la sélection d'une touche :

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

Action est plus communément utilisé pour des choses comme List<T>.ForEach : exécuter l'action donnée pour chaque élément de la liste. Je l'utilise moins souvent que Func bien que je faire utilisent parfois la version sans paramètre pour des choses comme Control.BeginInvoke y Dispatcher.BeginInvoke .

Predicate est juste un boîtier spécial Func<T, bool> vraiment, introduit 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 y Action sous leurs différentes formes, Predicate n'aurait pas été introduite... bien qu'elle fait confèrent un certain sens à l'utilisation du délégué, alors que Func y Action sont utilisés à des fins très différentes.

Predicate est surtout utilisé dans List<T> pour des méthodes comme FindAll y RemoveAll .

84 votes

J'aime bien voir Predicate dans une signature de fonction. Il illustre le fait que la méthode transmise prend une décision plutôt que de simplement renvoyer un code de réussite ou un autre type d'information. bool .

8 votes

Existe-t-il un guide de conception permettant de savoir s'il faut préférer Predicate<T> o Func<T,bool> ? J'aime l'expressivité de Predicate mais j'ai vu des recommandations pour Func aussi.

6 votes

@Ron : Oui, c'est à peu près ce dont parlait mon avant-dernier paragraphe.

431voto

Knasterbax Points 1383

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.

Func 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 une référence).

Prédicat est un type spécial de Func souvent utilisé pour les comparaisons (prend un paramètre générique et retourne un bool).

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;
    }
}

40 votes

Predicate est un délégué qui prend des paramètres génériques et retourne des bools.

31 votes

Bel exemple ! Notez que vous pouvez également invoquer monAction en l'appelant simplement : myAction(123); . Vous n'avez pas besoin d'utiliser .Invoke()

0 votes

Et juste pour être complet, si vous voulez utiliser un Func qui ne prend pas de paramètres mais retourne une valeur (ou une référence), vous devez écrire quelque chose comme ceci Func<double> monFoo = nouveau Func<double>(foo) ; et la définition de foo pourrait être static double foo(){return 1.0;}

67voto

Justin Niessner Points 144953

Func - 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 de 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 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 (vrai pour une correspondance, faux sinon). Encore une fois, ceux-ci sont utilisés dans LINQ assez fréquemment 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 trop pourquoi ils ont pris cette décision... mais théoriquement, c'est toujours une situation où un prédicat pourrait convenir.

3 votes

Je sais que c'est vieux, mais Predicate n'a pas été utilisé par LINQ parce qu'il est antérieur aux Func et Action que nous connaissons aujourd'hui, et ces deux derniers peuvent être utilisés pour obtenir exactement le même résultat d'une bien meilleure manière.

1 votes

@gparent, pourquoi est-ce mieux ? Je pense que la lisibilité est meilleure lorsque des délégués nommés de manière significative sont utilisés au lieu de Func o Action .

2 votes

Cela dépend de l'utilisation que l'on fait des délégués, mais parfois le nom n'est pas si important et le fait de devoir créer des fonctions et des variables pour une seule utilisation diminue la lisibilité.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X