开发者

When using LINQ, what is the difference between && and multiple where clauses?

开发者 https://www.devze.com 2022-12-09 16:54 出处:网络
I am new to LINQ and discovered yesterday that 开发者_运维百科you can have multiple where clauses such as:

I am new to LINQ and discovered yesterday that 开发者_运维百科you can have multiple where clauses such as:

var items = from object in objectList
where object.value1 < 100  
where object.value2 > 10  
select object;

Or you can write:

var items = from object in objectList
where object.value1 < 100  
   && object.value2 > 10  
select object;

What is the difference between the two?


The first one will be translated into:

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

while the second one will be translated in:

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

So, in the first one, you will have a first filtered sequence that is filtered again (first sequence contains all the objects with value < 100, the second one containing all the objects with value > 10 from the first sequence), in while the second one you will do the same comparisons in the same labda expression. This is valid fro Linq to objects, for other providers it depends how the expression is translated.


The marked answer gets it a little bit inaccurate.

As @Philippe said, the first one will be translated into:

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

while the second one will be translated in:

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

But Linq has a little optimization for chained Where calls.

If you inspect Linq's source code you will see the following:

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

What CombinePredicates does is is combining the two predicates with && between them:

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

So objectList.Where(X).Where(Y) is equivalent to objectList.Where(X && Y) except for the creation time of the query (Which is extremely short anyway) and the invocation of two predicates.

Bottom line is that it does not filter or iterate the collection two times - but one composite time.


The first one translates to:

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

while the latter gets you:

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

It's functionally the same, and while the second one would spare a method call, the difference in performance is negligible. Use what's more readable for you.

That is, if you're using LINQ to Objects. If you're using a provider, it depends on how it's implemented (if the predicate is not factored in the resulting query, the result can be sub-optimal).


I've just profile it. No difference in SQL code


At the most basic level, you get two Where operations instead of one. Using Reflector is the best way to examine what comes out the other end of a query expression.

Whether they get optimised down to the same thing depends on the actual LINQ provider - it needs to take the entire tree and convert it to another syntax. For LINQ To Objects, it doesn't.

C# in Depth is good to give you an understanding of this topic.


How about this for an answer: with && you can't guarantee that both expressions with be evaluated (if the first condition is false then the second might not be evaluated). With the two where clauses then you can. No idea whether it's true but it sounds good to me!


All other things being equal, I would choose the condition1 && condition2 version, for the sake of code readability.

0

精彩评论

暂无评论...
验证码 换一张
取 消