-1

When including multiple Where clauses in a Linq to object expression, will they evaluates short-circuiting like the && operator? Meaning will condition B only be evaluated if condition A return true

For example collection.Where(condition1).Where(condition2)

(Not talking about Linq to sql that will not do that even with the && operator short-circuiting-in-linq-where)

Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
JG3
  • 53
  • 2
  • 9
  • When you ran the code and tested to see whether or not the second condition actually ran what happened? Did it execute, or not? – Servy Dec 13 '18 at 22:47
  • 1
    if you have `SomeCollection.Where(predicate1).Where(predicate2)`, then it will be evaluated as `SomeCollection.Where(predicate1)` (i.e., the collection may be reduced based on whether the items in the collection match the predicate. That will return a new enumeration(possibly representing the same collection, possibly representing a reduced size collection, possibly and representing an empty collection). Then that second predicate will be applied, and the resulting enumeration will be returned. So, **no** – Flydog57 Dec 13 '18 at 22:49
  • 1
    @Flydog57 If all of this "That will return a new collection (possibly the same collection, possibly a reduced size collection, possibly and empty collection)" was with *Enumeration* instead of *Collection*, it would be correct – Camilo Terevinto Dec 13 '18 at 22:51
  • 2
    @Flydog57 LINQ operations return *queries*, not *the results of those queries*. – Servy Dec 13 '18 at 22:51
  • When i tested it looks like it will evaluates short-circuiting, i want to know if this is how it is implemented, i want to make sure that this will ALWAYS be the rule and i can be comfortable when doing multiple filters on properties that may be null – JG3 Dec 13 '18 at 22:52
  • 1
    @JoelG If you want to know if `Where` is ever documented as yielding items where the predicate is `false` for that item, you could read the documentation, if you *really* want an official source of it. Does the documentation for the method give you the impression that it might end up yielding items where the predicate is false? – Servy Dec 13 '18 at 22:56
  • @Servy i want to know if i can apply multiple filters on an object if evaluating condition2 when condition1 is false might throw an error – JG3 Dec 13 '18 at 23:05
  • @JoelG Yes. And to answer that question, you apparently tested it, and found that it doesn't in fact do that, and then said that you want an official guarantee that `Where` will never yield items that don't pass the predicate, at which point I asked if you'd looked at the documentation for `Where`, as that should give you the official guarantee that you want. – Servy Dec 13 '18 at 23:09
  • @Servy i did a basic search on Microsoft.com and didn't find the answer, maybe i am missing a reference – JG3 Dec 13 '18 at 23:18
  • @JoelG I would suggest just searching Google, but anyways, [here](https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.where?view=netframework-4.7.2) is the documentation for the `Where` method. You can see that it's documented as returning a sequence containing only the items that satisfy the condition. – Servy Dec 13 '18 at 23:20
  • @Servy i was looking on something concrete like the test Camilo Terevinto did that proovs it 100%, (or any documentation that i didn't find) i just didn't have the idea how to go about it... – JG3 Dec 13 '18 at 23:27
  • @JoelG But you [said earlier](https://stackoverflow.com/questions/53771135/linq-to-object-multiple-where-short-circuit-evaluation/53771199?noredirect=1#comment94394245_53771135) that you did test it, and your results showed that it doesn't execute, and that you wanted a guarantee above and beyond your tests... – Servy Dec 13 '18 at 23:28
  • My test didn't throw an error which is good and i can probably rely on it, his test clearly show that its not reach that piece of code Anyway i now know that i can just continue doing what i did.. Thanks – JG3 Dec 13 '18 at 23:33

1 Answers1

1

Let's take a look at some more code. We'll test both scenarios:

  1. First we will test for && by using two if statements
  2. We'll use two Where calls

So:

var elements = new List<string>(new[] { "A", "B", "C" });

Console.WriteLine("C#'s &&");

elements.Where(x => {
    if (x == "A")
    {
        Console.WriteLine("ConditionA is true");
        if (1 == 1)
        {
            Console.WriteLine("ConditionB is true");
            return true;
        }

        Console.WriteLine("ConditionB is false");
    }

    Console.WriteLine("ConditionA is false");

    return false;           
}).ToList();

Console.WriteLine();
Console.WriteLine("Double Linq.Where");

elements.Where(x => {
    if (x == "A")
    {
        Console.WriteLine("ConditionA is true");
        return true;
    }

    Console.WriteLine("ConditionA is false");
    return false;           
})
    .Where(x => {
        if (1 == 1)
        {
            Console.WriteLine("ConditionB is true");
            return true;
        }

        Console.WriteLine("ConditionB is false");
        return false;
    }).ToList();

Here are the results:

C#'s &&
ConditionA is true
ConditionB is true
ConditionA is false
ConditionA is false

Double Linq.Where
ConditionA is true
ConditionB is true
ConditionA is false
ConditionA is false

As you can see, it's the same. Elements that don't pass ConditionA aren't tested for ConditionB.
You can try this out here: https://dotnetfiddle.net/vals2r

Camilo Terevinto
  • 31,141
  • 6
  • 88
  • 120
  • Apparently [the OP already did this](https://stackoverflow.com/questions/53771135/linq-to-object-multiple-where-short-circuit-evaluation?noredirect=1#comment94394245_53771135) before asking this question. – Servy Dec 13 '18 at 23:09
  • @Servy Huh, I missed that comment while playing around. Thanks – Camilo Terevinto Dec 13 '18 at 23:10