Nov 25

Ce billet présente quelques astuces permettant de rendre les instructions Linq plus lisibles, plus facilement maintenables et plus performantes.
J’ai déjà utilisé ces astuces dans des cas réels, avec parfois des résultats assez impressionnants !

Where().Count() > 0

Il s’agit d’une instruction très fréquemment rencontrée :

if(myList.Where(p => p.Age > 18).Count() > 0)

Or, ce que veut savoir le développeur c’est s’il y a un élément dans la liste qui correspond au critère, pas le nombre d’élément.
Sur une énumération, le Count() n’est performant que si le type sous-jacent implémente ICollection (Linq s’applique à tous les types implémentant IEnumerable) car dans ce cas, Count() va renvoyer la propriété ICollection.Count, la complexité sera O(1) dans ce cas spécifique.
Pour les autres cas, l’ensemble des éléments de la liste seront comptés un à un, la complexité sera de O(n).

De plus, dans notre cas avec le Where(), Linq va parcourir l’intégralité de la liste myList pour appliquer son filtre, puis compter le nombre de résultats. Deux opérations totalement inutiles.

Ce code devrait être remplacé par :

if(myList.Any(p => p.Age > 18))

Car Any() va renvoyer True dès qu’elle va rencontrer un élément correspondant au critère, donc il n’est pas nécessaire de parcourir toute la liste (sauf s’il n’y a aucun élément correspondant, mais dans ce cas la complexité est au pire de O(n), au mieux elle est de O(1))

A noter qu’il est toujours plus intéressant d’utiliser Any() plutôt que Count() même lorsqu’il n’y a pas de Where(), car Any() sans paramètres (permettant de savoir si l’énumération contient au moins 1 élément) a toujours une complexité de O(1).

Where().First()

Problème similaire au précédent :

var item = myList.Where(p => p.Age > 18).First()

L’objectif ici est de récupérer le premier élément correspondant à un critère.
Le souci avec ce code est le même qu’avec le Count(), c’est que cette opération implique forcément de parcourir l’intégralité des éléments, pour ensuite ne prendre que le premier.

Ainsi, utiliser le code suivant peut améliorer les performances et simplifie nettement le code :

var item = myList.First(p => p.Age > 18)

Cette astuce peut être appliquée à de nombreuses méthodes Linq, donc il est toujours intéressant de jeter un oeil aux surcharges disponibles.

via James Michael Hare

Leave a Reply