Sûrement la raison pour l'utilisation de Func
au lieu d'un délégué spécifique est que C# traite séparément déclaré les délégués totalement différents types.
Même si Func<int, bool>
et Predicate<int>
les deux ont le même argument et types de retour, ils ne sont pas compatible avec l'assignation. Donc, si chaque bibliothèque a déclaré son propre type de délégué pour chaque modèle de délégué, ces bibliothèques ne serait pas en mesure d'interopérer, à moins que l'utilisateur insère la "transition" délégués d'effectuer des conversions.
// declare two delegate types, completely identical but different names:
public delegate void ExceptionHandler1(Exception x);
public delegate void ExceptionHandler2(Exception x);
// a method that is compatible with either of them:
public static void MyExceptionHandler(Exception x)
{
Console.WriteLine(x.Message);
}
static void Main(string[] args)
{
// can assign any method having the right pattern
ExceptionHandler1 x1 = MyExceptionHandler;
// and yet cannot assign a delegate with identical declaration!
ExceptionHandler2 x2 = x1; // error at compile time
}
En encourageant tout le monde à utiliser la touche Func, Microsoft espère que cela va résoudre le problème de l'incompatibilité des types délégués. Tous les délégués jouent bien ensemble, parce qu'ils seront appariés sur la base de leurs paramètres/types de retour.
Il ne résout pas tous les problèmes, car Func
(et Action
) ne peuvent pas avoir l' out
ou ref
paramètres, mais ceux qui sont moins fréquemment utilisés.
Mise à jour: dans les commentaires Svish dit:
Encore, la commutation d'un type de paramètre de
Func pour Prédicat et
de retour, ne semblent pas tout
la différence? Au moins il encore compile
sans aucun problème.
Oui, aussi longtemps que votre programme n'attribue méthodes pour les délégués, comme dans la première ligne de mon Main
fonction. Le compilateur silencieusement génère un code à nouveau un délégué de l'objet qui la transmet à la méthode. Donc, dans mon Main
de la fonction, je pourrais changer de x1
pour être de type ExceptionHandler2
sans causer un problème.
Cependant, sur la deuxième ligne j'essaie d'attribuer le premier délégué à un autre délégué. Même pensé que 2e délégué type a exactement le même paramètre et types de retour, le compilateur donne erreur CS0029: Cannot implicitly convert type 'ExceptionHandler1' to 'ExceptionHandler2'
.
Peut-être cela va le rendre plus clair:
public static bool IsNegative(int x)
{
return x < 0;
}
static void Main(string[] args)
{
Predicate<int> p = IsNegative;
Func<int, bool> f = IsNegative;
p = f; // Not allowed
}
Ma méthode IsNegative
est une très bonne chose pour l'attribuer à l' p
et f
variables, aussi longtemps que je le faire directement. Mais alors je ne peux pas attribuer un de ces variables à l'autre.