我是LINQ的新手,昨天发现你可以有多个where子句,如:
var items = from object in objectList
where object.value1 < 100
where object.value2 > 10
select object;
或者你可以写:
var items = from object in objectList
where object.value1 < 100
&& object.value2 > 10
select object;
两者有什么区别?
答案 0 :(得分:18)
第一个将被翻译成:
objectList.Where(o => o.value1 < 100).Where(o=> o.value2 > 10)
而第二个将翻译成:
objectList.Where(o => o.value1 < 100 && o.value2 > 10)
因此,在第一个中,您将有一个第一个过滤的序列再次过滤(第一个序列包含值<100的所有对象,第二个序列包含值>&gt;所有第一个序列的对象),在第二个你将在同一个labda表达式中进行相同的比较。这对于Linq到对象是有效的,对于其他提供者,它取决于表达式的翻译方式。
答案 1 :(得分:10)
标记的答案有点不准确。
正如@Philippe所说,第一个将被翻译成:
objectList.Where(o => o.value1 < 100).Where(o=> o.value2 > 10)
而第二个将翻译成:
objectList.Where(o => o.value1 < 100 && o.value2 > 10)
但是 Linq
对链式Where
电话进行了一些优化。
如果您检查Linq's
源代码,您会看到以下内容:
class WhereEnumerableIterator<TSource> : Iterator<TSource>
{
public override IEnumerable<TSource> Where(Func<TSource, bool> predicate)
{
return new WhereEnumerableIterator<TSource>(source,
CombinePredicates(this.predicate, predicate));
}
}
CombinePredicates
的作用是将两个谓词与&&
组合在一起:
static Func<TSource, bool> CombinePredicates<TSource>(Func<TSource, bool> predicate1,
Func<TSource, bool> predicate2)
{
return x => predicate1(x) && predicate2(x);
}
所以objectList.Where(X).Where(Y)
等同于objectList.Where(X && Y)
,除了查询的创建时间(无论如何都非常短)和两个谓词的调用。
底线是 它不 过滤或迭代集合两次 - 但是一个复合时间。
答案 2 :(得分:6)
第一个转换为:
objectList.Where(o => o.value1 < 100)
.Where(o => o.value2 > 10);
而后者得到你:
objectList.Where(o => o.value1 < 100 && o.value2 > 10);
它的功能完全相同,虽然第二个会省去方法调用,但性能上的差异可以忽略不计。使用对您而言更具可读性的内容。
也就是说,如果你使用linq来对象。如果您正在使用提供程序,则取决于它的实现方式(如果在结果查询中未考虑谓词,则结果可能是次优的。)
答案 3 :(得分:3)
我只是简介它。 SQL代码没有区别
答案 4 :(得分:1)
在最基本的级别,您将获得两个Where操作而不是一个。使用Reflector是检查查询表达式另一端出现的内容的最佳方法。
它们是否优化到同一个东西取决于实际的LINQ提供程序 - 它需要占用整个树并将其转换为另一种语法。对于LINQ To Objects,它没有。
C# in Depth很高兴让您了解这个主题。
答案 5 :(得分:0)
这个答案怎么样:和&amp;&amp;你不能保证两个表达式都要被评估(如果第一个条件是假,那么第二个条件可能不被评估)。有了两个where子句就可以了。不知道这是否属实,但对我来说听起来不错!
答案 6 :(得分:0)
在所有其他条件相同的情况下,为了代码可读性,我会选择condition1 && condition2
版本。