Mise à jour :
J'ai reçu de très bons commentaires sur ma réponse, qui m'ont fait réfléchir. Je vais donc d'abord fournir la réponse qui expose mon "nouveau" point de vue ; vous pouvez toujours trouver ma réponse originale juste en dessous. Assurez-vous de lire les commentaires entre les deux pour comprendre où ma première réponse n'est pas pertinente.
Nouvelle réponse :
Supposons que Single
doit lever une exception lorsque sa condition préalable n'est pas remplie, c'est-à-dire lorsque Single
détecte que soit aucun, soit plus d'un élément de la collection correspond au prédicat.
Single
ne peut réussir sans lever d'exception qu'en parcourant l'ensemble de la collection. Il doit s'assurer qu'il y a exactement un élément correspondant, il devra donc vérifier tous les éléments de la collection.
Cela signifie que le lancement précoce d'une exception (dès qu'il trouve un deuxième élément correspondant) est essentiellement une optimisation dont vous ne pouvez bénéficier que lorsque Single
Si la condition préalable de l'utilisateur ne peut pas être remplie, une exception sera levée.
Comme le dit clairement l'utilisateur CodeInChaos dans un commentaire ci-dessous, l'optimisation ne serait pas mauvaise, mais elle n'a pas de sens, car on introduit généralement des optimisations qui profiteront à un code qui fonctionne correctement, et non des optimisations qui profiteront à un code qui fonctionne mal.
Ainsi, il est en fait correct que Single
pourrait lever une exception prématurément, mais il n'est pas nécessaire de le faire, car il n'y a pratiquement aucun avantage supplémentaire.
Vieille réponse :
Je ne peux pas donner de raison technique por qué cette méthode est implémentée comme elle l'est, puisque je ne l'ai pas implémentée. Mais je peux affirmer ma compréhension de la Single
de l'opérateur objectif et j'en tire la conclusion personnelle qu'il est effectivement mal mis en œuvre :
Ma compréhension de Single
:
Quel est le but de Single
et quelle est la différence avec, par exemple, l'utilisation d'une carte de crédit. First
o Last
?
Utilisation de la Single
exprime fondamentalement l'hypothèse que l'on doit retourner exactement un élément de la collection :
-
Si vous ne spécifiez pas de prédicat, cela signifie que la collection doit contenir exactement un élément.
-
Si vous spécifiez un prédicat, cela signifie qu'un seul élément de la collection doit satisfaire à cette condition. (L'utilisation d'un prédicat devrait avoir le même effet que items.Where(predicate).Single()
.)
C'est ce qui rend Single
différent d'autres opérateurs tels que First
, Last
o Take(1)
. Aucun de ces opérateurs n'exige qu'il y ait exactement un article (correspondant).
Quand faut-il Single
lancer une exception ?
En fait, lorsqu'il constate que votre hypothèse était erronée, c'est-à-dire lorsque la collection sous-jacente est no donnent exactement un élément (correspondant). C'est-à-dire lorsqu'il y a zéro ou plus d'un élément.
Quand faut-il Single
être utilisé ?
L'utilisation de Single
est approprié lorsque la logique de votre programme peut garantir que la collection donnera exactement un élément, et un seul. Si une exception est levée, cela signifie que la logique de votre programme contient un bug.
Si vous traitez des collections "peu fiables", telles que les entrées E/S, vous devez d'abord valider les entrées avant de les transmettre à l'application Single
. Single
ainsi qu'une exception catch
bloc, est no approprié pour s'assurer que la collection n'a qu'un seul élément correspondant. Au moment où vous invoquez Single
vous devriez déjà ont fait en sorte qu'il n'y ait qu'un seul article correspondant.
Conclusion :
Ce qui précède indique ma compréhension de la Single
Opérateur LINQ. Si vous suivez et êtes d'accord avec cette compréhension, vous devriez arriver à la conclusion que Single
devrait lever une exception le plus tôt possible . Il n'y a aucune raison d'attendre jusqu'à la fin de la collection (qui peut être très grande), car la pré-condition de Single
est violée dès qu'elle détecte un deuxième élément (correspondant) dans la collection.