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.