dans l' System.Linq
espace de noms, nous pouvons maintenant étendre nos IEnumerables pour avoir les méthodes d'extension Any () et Count () .
On m'a dit récemment que si je veux vérifier qu'une collection contient 1 ou plusieurs éléments à l'intérieur, je devrais utiliser la .Any()
méthode d'extension au lieu de la .Count() > 0
méthode d'extension car la .Count()
méthode d'extension doit parcourir tous les éléments.
Deuxièmement, certaines collections ont une propriété (pas une méthode d'extension) qui est Count
ou Length
. Serait-il préférable de les utiliser à la place de .Any()
ou .Count()
?
oui / nae?
.net
linq
performance
.net-3.5
extension-methods
Pure.Krome
la source
la source
Réponses:
Si vous commencez par quelque chose qui a un
.Length
ou.Count
(commeICollection<T>
,IList<T>
,List<T>
, etc.) - alors ce sera l'option la plus rapide, car il n'a pas besoin de passer par laGetEnumerator()
/MoveNext()
/Dispose()
séquence requise parAny()
vérifier pour un non-videIEnumerable<T>
séquence .Pour seulement
IEnumerable<T>
, puisAny()
sera généralement plus rapide, car il n'a qu'à regarder une seule itération. Cependant, notez que l'implémentation LINQ-to-ObjectsCount()
vérifieICollection<T>
(en.Count
tant qu'optimisation) - donc si votre source de données sous-jacente est directement une liste / collection, il n'y aura pas de différence énorme. Ne me demandez pas pourquoi il n'utilise pas le non génériqueICollection
...Bien sûr, si vous avez utilisé LINQ pour le filtrer, etc. (
Where
etc), vous aurez une séquence basée sur un bloc d'itérateur, et donc cetteICollection<T>
optimisation est inutile.En général avec
IEnumerable<T>
: coller avecAny()
;-pla source
(somecollection.Count > 0)
? Tout notre code avant l'introduction de la méthode .Any () de LINQ était-il difficile à comprendre?someCollection.Count > 0
c'est aussi clair quesomeCollection.Any()
et a l'avantage supplémentaire de meilleures performances et de ne pas nécessiter LINQ. Certes, il s'agit d'un cas très simple et d'autres constructions utilisant des opérateurs LINQ véhiculeront l'intention des développeurs beaucoup plus clairement que l'option non LINQ équivalente.Remarque: J'ai écrit cette réponse lorsque Entity Framework 4 était réel. Le but de cette réponse n'était pas d'entrer dans des tests triviaux
.Any()
contre des.Count()
performances. Le but était de signaler que EF est loin d'être parfait. Les versions plus récentes sont meilleures ... mais si vous avez une partie de code qui est lente et utilise EF, testez avec TSQL direct et comparez les performances plutôt que de vous fier à des hypothèses (c'est.Any()
TOUJOURS plus rapide que.Count() > 0
).Bien que je sois d'accord avec la réponse et les commentaires les plus votés - en particulier sur le point
Any
, l' intention du développeur est meilleure queCount() > 0
- j'ai eu une situation dans laquelle Count est plus rapide par ordre de grandeur sur SQL Server (EntityFramework 4).Voici la requête avec
Any
cette exception de délai d'attente (sur environ 200 000 enregistrements):Count
version exécutée en quelques millisecondes:J'ai besoin de trouver un moyen de voir quel SQL exact les deux LINQ produisent - mais il est évident qu'il y a une énorme différence de performances entre
Count
etAny
dans certains cas, et malheureusement il semble que vous ne pouvez pas simplement vous en tenirAny
à tous les cas.EDIT: Voici les SQL générés. Des beautés comme vous pouvez le voir;)
ANY
:COUNT
:Il semble que pur Where avec EXISTS fonctionne bien pire que de calculer Count puis de faire Where with Count == 0.
Faites-moi savoir si vous voyez des erreurs dans mes conclusions. Ce qui peut être retiré de tout cela indépendamment de la discussion Any vs Count, c'est que tout LINQ plus complexe est beaucoup mieux lorsqu'il est réécrit en tant que procédure stockée;).
la source
Comme c'est un sujet assez populaire et que les réponses diffèrent, j'ai dû jeter un regard neuf sur le problème.
Test d'env: EF 6.1.3, SQL Server, 300k enregistrements
Modèle de table :
Code de test:
Résultats:
Tout () ~ 3 ms
Count () ~ 230 ms pour la première requête, ~ 400 ms pour la seconde
Remarques:
Pour mon cas, EF n'a pas généré de SQL comme @Ben mentionné dans son article.
la source
Count() > 0
. : DEDIT: il a été corrigé dans EF version 6.1.1. et cette réponse n'est plus d'actualité
Pour SQL Server et EF4-6, Count () fonctionne environ deux fois plus rapidement que Any ().
Lorsque vous exécutez Table.Any (), cela générera quelque chose comme ( alerte: ne blessez pas le cerveau en essayant de le comprendre )
cela nécessite 2 scans de lignes avec votre condition.
Je n'aime pas écrire
Count() > 0
car cela cache mon intention. Je préfère utiliser un prédicat personnalisé pour cela:la source
Cela dépend, quelle est la taille de l'ensemble de données et quelles sont vos exigences de performance?
Si ce n'est rien de gigantesque, utilisez la forme la plus lisible, qui est pour moi, car elle est plus courte et lisible plutôt qu'une équation.
la source
À propos de la méthode Count () , si le IEnumarable est un ICollection , nous ne pouvons pas parcourir tous les éléments car nous pouvons récupérer le champ Count de ICollection , si le IEnumerable n'est pas un ICollection, nous devons parcourir tous les éléments en utilisant un moment avec un MoveNext , jetez un œil au code .NET Framework:
Référence: source de référence énumérable
la source
Vous pouvez faire un test simple pour comprendre cela:
Vérifiez les valeurs de testCount et testAny.
la source
Count
méthode Count () vs .Any () n'est pas une propriété. Vous avez besoin de temps d'itérations.Si vous utilisez Entity Framework et disposez d'une énorme table avec de nombreux enregistrements, Any () sera beaucoup plus rapide. Je me souviens d'une fois où j'ai voulu vérifier si une table était vide et qu'elle avait des millions de lignes. Il a fallu 20 à 30 secondes pour que Count ()> 0 se termine. C'était instantané avec Any () .
Any () peut être une amélioration des performances car il peut ne pas avoir à itérer la collection pour obtenir le nombre de choses. Il suffit de frapper l'un d'eux. Ou, pour, disons, LINQ-to-Entities, le SQL généré sera IF EXISTS (...) plutôt que SELECT COUNT ... ou même SELECT * ....
la source