Ceci est juste une question de curiosité, je me demandais si quelqu'un avait une bonne réponse à:
Dans la bibliothèque de classes .NET Framework, nous avons par exemple ces deux méthodes:
public static IQueryable<TSource> Where<TSource>(
this IQueryable<TSource> source,
Expression<Func<TSource, bool>> predicate
)
public static IEnumerable<TSource> Where<TSource>(
this IEnumerable<TSource> source,
Func<TSource, bool> predicate
)
Pourquoi utilisent-ils Func<TSource, bool>
au lieu de Predicate<TSource>
? On dirait que le Predicate<TSource>
est uniquement utilisé par List<T>
et Array<T>
, alors qu'il Func<TSource, bool>
est utilisé par à peu près tous Queryable
et les Enumerable
méthodes et les méthodes d'extension ... qu'est-ce qui se passe?
Réponses:
Bien qu'il
Predicate
ait été introduit en même temps queList<T>
etArray<T>
dans .net 2.0, les différentsFunc
etAction
variantes proviennent de .net 3.5.Ces
Func
prédicats sont donc principalement utilisés pour la cohérence des opérateurs LINQ. À partir de .net 3.5, à propos de l'utilisationFunc<T>
etAction<T>
la directive indique :la source
Je me suis déjà posé la question. J'aime le
Predicate<T>
délégué - c'est sympa et descriptif. Cependant, vous devez tenir compte des surcharges deWhere
:Cela vous permet également de filtrer en fonction de l'index de l'entrée. C'est sympa et cohérent, alors que:
ne serait pas.
la source
Where
méthode d'extension estpredicate
. Heh = P.La raison réelle de l'utilisation
Func
au lieu d'un délégué spécifique est certainement que C # traite les délégués déclarés séparément comme des types totalement différents.Même si
Func<int, bool>
et lesPredicate<int>
deux ont arguments identiques et types de retour, ils ne sont pas compatibles avec l' affectation. Ainsi, si chaque bibliothèque déclarait son propre type de délégué pour chaque modèle de délégué, ces bibliothèques ne seraient pas en mesure d'interopérer à moins que l'utilisateur n'insère des délégués de "pontage" pour effectuer des conversions.En encourageant tout le monde à utiliser Func, Microsoft espère que cela résoudra le problème des types de délégués incompatibles. Les délégués de chacun joueront bien ensemble, car ils seront juste mis en correspondance en fonction de leurs paramètres / types de retour.
Il ne résout pas tous les problèmes, parce que
Func
(etAction
) ne peuvent pas avoirout
ouref
paramètres, mais ceux -ci sont moins fréquemment utilisés.Mise à jour: dans les commentaires Svish dit:
Oui, tant que votre programme affecte uniquement des méthodes aux délégués, comme dans la première ligne de ma
Main
fonction. Le compilateur génère silencieusement du code pour créer un nouvel objet délégué qui le transmet à la méthode. Donc, dans maMain
fonction, je pouvais changerx1
de typeExceptionHandler2
sans causer de problème.Cependant, sur la deuxième ligne, j'essaie d'affecter le premier délégué à un autre délégué. Même si le deuxième type de délégué a exactement les mêmes paramètres et types de retour, le compilateur donne une erreur
CS0029: Cannot implicitly convert type 'ExceptionHandler1' to 'ExceptionHandler2'
.Peut-être que cela le rendra plus clair:
Ma méthode
IsNegative
est une très bonne chose à attribuer aux variablesp
etf
, tant que je le fais directement. Mais alors je ne peux pas assigner une de ces variables à l'autre.la source
Func<T, bool>
ouPredicate<T>
plutôt que d'avoir le type déduit par le compilateur.Le conseil (en 3.5 et supérieur) est d'utiliser le
Action<...>
etFunc<...>
- pour le "pourquoi?" - un avantage est que "Predicate<T>
" n'a de sens que si vous savez ce que signifie "prédicat" - sinon vous devez regarder le navigateur d'objets (etc) pour trouver le signataire.Inverse
Func<T,bool>
suit un modèle standard; Je peux immédiatement dire que c'est une fonction qui prend unT
et retourne unbool
- pas besoin de comprendre la terminologie - il suffit d'appliquer mon test de vérité.Pour "prédicat", cela aurait pu être OK, mais j'apprécie la tentative de normalisation. Il permet également une grande parité avec les méthodes associées dans ce domaine.
la source