Lorsque vous utilisez LINQ, quelle est la différence entre les clauses && et les clauses where multiples?

Je suis nouveau sur LINQ et j’ai découvert hier que vous pouvez avoir plusieurs clauses where telles que:

var items = from object in objectList where object.value1  10 select object; 

Ou vous pouvez écrire:

 var items = from object in objectList where object.value1  10 select object; 

Quelle est la différence entre les deux?

Le premier sera traduit en:

 objectList.Where(o => o.value1 < 100).Where(o=> o.value2 > 10) 

tandis que le second sera traduit en:

 objectList.Where(o => o.value1 < 100 && o.value2 > 10) 

Ainsi, dans la première, vous aurez une première séquence filtrée qui est filtrée à nouveau (la première séquence contient tous les objects de valeur <100, la seconde contenant tous les objets de valeur> 10 de la première séquence), en Deuxièmement, vous ferez les mêmes comparaisons dans la même expression labda. Ceci est valable de Linq aux objects, pour d’autres fournisseurs, cela dépend de la façon dont l’expression est traduite.

La réponse marquée devient un peu inexacte.

Comme @Philippe l’a dit, le premier sera traduit en:

 objectList.Where(o => o.value1 < 100).Where(o=> o.value2 > 10) 

tandis que le second sera traduit en:

 objectList.Where(o => o.value1 < 100 && o.value2 > 10) 

Mais Linq a une petite optimisation pour les appels Where chaînés.

Si vous inspectez Linq's code source Linq's vous verrez ce qui suit:

 class WhereEnumerableIterator : Iterator { public override IEnumerable Where(Func predicate) { return new WhereEnumerableIterator(source, CombinePredicates(this.predicate, predicate)); } } 

CombinePredicates combine les deux prédicats avec && entre eux:

 static Func CombinePredicates(Func predicate1, Func predicate2) { return x => predicate1(x) && predicate2(x); } 

Donc objectList.Where(X).Where(Y) équivaut à objectList.Where(X && Y) exception du temps de création de la requête (ce qui est extrêmement court) et de l’invocation de deux prédicats.

En bout de ligne, il ne filtre ni n’itère la collection deux fois, mais une seule fois.

Le premier se traduit par:

 objectList.Where(o => o.value1 < 100) .Where(o => o.value2 > 10); 

pendant que ce dernier vous obtient:

 objectList.Where(o => o.value1 < 100 && o.value2 > 10); 

C’est fonctionnellement le même, et bien que le second épargnerait un appel de méthode, la différence de performance est négligeable. Utilisez ce qui est plus lisible pour vous.

Autrement dit, si vous utilisez linq pour les objects. Si vous utilisez un fournisseur, cela dépend de la manière dont il est implémenté (si le prédicat n’est pas factorisé dans la requête résultante, le résultat peut être sous-optimal).

Je viens de le profiler. Aucune différence dans le code SQL

Au niveau le plus élémentaire, vous obtenez deux opérations Où au lieu d’une. L’utilisation de Reflector est le meilleur moyen d’examiner ce qui sort de l’autre extrémité d’une expression de requête.

Le fait qu’ils soient optimisés ou non dépend du fournisseur LINQ lui-même. Il doit alors convertir l’arborescence complète en une autre syntaxe. Pour LINQ To Objects, ce n’est pas le cas.

C # in Depth est bon pour vous donner une compréhension de ce sujet.

Que diriez-vous de cela pour une réponse: avec && vous ne pouvez pas garantir que les deux expressions seront évaluées (si la première condition est fausse, la seconde pourrait ne pas être évaluée). Avec les deux clauses où alors vous pouvez. Je ne sais pas si c’est vrai, mais ça me semble bien!

Toutes choses égales par ailleurs, je choisirais la version condition1 && condition2 , dans un souci de lisibilité du code.