Avec des exemples réels et leur utilisation, quelqu'un peut-il m'aider à comprendre :
- Quand avons-nous besoin d'un
Func<T, ..>
délégué ? - Quand avons-nous besoin d'un
Action<T>
délégué ? - Quand avons-nous besoin d'un
Predicate<T>
délégué ?
Avec des exemples réels et leur utilisation, quelqu'un peut-il m'aider à comprendre :
Func<T, ..>
délégué ?Action<T>
délégué ?Predicate<T>
délégué ?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
.
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
.
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.
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;
}
}
Bel exemple ! Notez que vous pouvez également invoquer monAction en l'appelant simplement : myAction(123);
. Vous n'avez pas besoin d'utiliser .Invoke()
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;}
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.
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.
@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
.
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.
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.