2009-10-30 60 views
12

我是新来的LINQ和昨天发现,你可以有多个where子句,如:使用LINQ时,&&和multiple 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; 

两者有什么区别?

回答

17

第一个将被翻译成:

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

,而第二个将被翻译:

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

所以,在第一个,你将有一个第一过滤序列(第一个序列包含值为< 100的所有对象,第二个包含第一个序列中值> 10的所有对象),而第二个将在同一labda表达式中进行相同的比较。这对Linq是有效的,对于其他提供者,它依赖于表达式的翻译方式。

+1

其实这是相当不准确的。如果你检查'Linq'的源代码,你会看到'Where'有一个将'.Where(x).Where(y)'转换成'.Where(x && y)'的方法。 [源代码](http://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,f7e72dc9c9621f30) –

+0

好点,我无法说如果我在2009年检查过它,或者如果它是一直如此。 – Philippe

1

在最基本的层面上,你会得到两个Where操作而不是一个操作。使用Reflector是检查查询表达式的另一端的最佳方法。

它们是否被优化到相同的事情取决于实际的LINQ提供者 - 它需要将整个树并将其转换为另一种语法。对于LINQ To Objects,它没有。

C# in Depth很好地给你一个理解这个话题。

6

第一个翻译为:

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

而后者则让你:

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

这functionnaly相同的,而第二个会不遗余力的方法调用,在性能上的差异可以忽略不计。使用更可读的东西。

也就是说,如果你使用linq的对象。如果您使用提供程序,则取决于它的实现方式(如果谓词未包含在生成的查询中,则结果可能不是最优的)。

+0

我实际上直接输入了它。你是对的,身份选择者没有意义。 –

0

这个如何回答:& &你不能保证两个表达式都被评估(如果第一个条件是假的,那么第二个条件可能不会被评估)。你可以用两个where子句。不知道它是否属实,但对我来说听起来不错!

+2

我不认为这是真的。如果它是Linq到Objects,那么第一个Where-call将返回一个只包含条件1为true的项目的枚举。所以条件2只会被要求这些项目。 – Niki

+0

没错,但事实并非如此?假设你使用一个简单的'&',那么两者都将在第二种情况下被评估。无论如何,最好避免在这些使用副作用:) – Philippe

0

所有其他的东西都是平等的,我会选择condition1 && condition2版本,为了代码的可读性。

3

我只是简介它。 SQL代码无差异

+0

假设OP是在谈论LINQ to SQL。 =) –

6

标记的答案让它有点不准确。

正如@Philippe说,第一个将被翻译成:

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

但是Linq具有:

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

而第二个将被转换对链接的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)除了查询的创建时间(无论如何都非常短)和调用两个谓词。

底线是它不过滤器或重复收集两次 - 而是一个复合的时间。