Tân
Tân

Reputation: 1

Using || operator in LinQ

I've a small example to use || operator with Where() but something may be wrong:

var list = new List<string>
{
   "One",
   "Two",
   "Three"
};

string s = "One";
var numbers = list.Where(x => x == s || !string.IsNullOrEmpty(x));

foreach(var number in numbers)
{
   Console.WriteLine(number);

   // output:
   // One
   // Two
   // Three
}

s = null;    
numbers = list.Where(x => x == s || !string.IsNullOrEmpty(x));

foreach(var number in numbers)
{
   Console.WriteLine(number);

   // output:
   // One
   // Two
   // Three
}

In the first case, why was !string.IsNullOrEmpty(x) still checked when we had x == s true?

I understood:

if (A && B)
{
   // we need A and B are true
}

if (A || B)
{
   // we need A is true or B is true
   // if A is true, no ned to check B is true or not
}

So, my question is: what did I misunderstand?

Upvotes: 1

Views: 3327

Answers (3)

Valentin
Valentin

Reputation: 5488

var numbers = list.Where(x => x == s || !string.IsNullOrEmpty(x)); takes each element from list - x and checks if it fits specific condition.

The condition is x == s OR !string.IsNullOrEmpty(x), so element should fit at least one part of the condition.

Particularly, every element of list meets the !string.IsNullOrEmpty(x) condition.

Try to add null to your list. It doesn't meet the !string.IsNullOrEmpty(x) and doesn't meet x == s, so it won't be included in result.

 var list = new List<string>
 {
        "One",
        "Two",
        "Three",
        null
 };

var numbers = list.Where(x => x == "One" || !string.IsNullOrEmpty(x)).ToList();

Upvotes: 4

Ian
Ian

Reputation: 30813

You are right in saying that:

a || b

Will not evaluate b if a is true, but:

Where LINQ using Lambda expression checks every element in the Enumerable regardless of the previous result. Thus when you do:

string s = "One";
var numbers = list.Where(x => x == s || !string.IsNullOrEmpty(x));

It checks every element in the query whenever the Where lambda expression is valid:

x == s || !string.IsNullOrEmpty(x)); //x = "One", x == s is true
x == s || !string.IsNullOrEmpty(x)); //x = "Two", !string.IsNullOrEmpty(x) is true
x == s || !string.IsNullOrEmpty(x)); //x = "Three", !string.IsNullOrEmpty(x) is true

Thus you got all the elements.

Consider using TakeWhile if you want to stop taking the query result as soon as a condition is no longer reached.

Upvotes: 8

James Dev
James Dev

Reputation: 3009

The operator is correct . In your first example:

string s = "One";
var numbers = list.Where(x => x == s || !string.IsNullOrEmpty(x));

foreach(var number in numbers)
{
   Console.WriteLine(number);

   // output:
   // One <-- First condition is met
   // Two <-- First condition is not met so goes into the OR operator and returns true
   // Three <--Same as above
}

https://msdn.microsoft.com/en-us/library/6373h346.aspx

Upvotes: 1

Related Questions