'Multiple using of || and && operands

I have a query using Entity Framework. It has many different operands and I am confused with its priority. I am getting the wrong result. I need all records that IsPaid == true or IsPaid == null, also all records must be TypeId == 1 or TypeId == 2, also must be CityId == 1 and CategoryId == 2. For some reason it doesn't evaluate CityId and CategoryId. What am I doing wrong? Thanks.

var list = db.Ads.Where (x =>
               x.IsPaid == true || x.IsPaid == null &&
               x.TypeId == 1 || x.TypeId == 2 &&
               x.CityId == 1 && x.CategoryId == 2
).ToList();


Solution 1:[1]

The best way to solve this problem is using brackets. You should always use them even if you know the binding prioritys, to increase readability of your code.

(x.IsPaid == true || x.IsPaid == null) && (x.TypeId == 1 || x.TypeId == 2) && x.CityId == 1 && x.CategoryId == 2


&& has a higher proirity than ||

So false && false || true would be translated to (false && false) || true => true


Sidenote as mentioned by @Joey:

Instead of (x.IsPaid == true || x.IsPaid == null) you can write (x.IsPaid != false).

Solution 2:[2]

Due to operator precedence, && binds higher than ||.

If you chain Where statements, it's more clear what happens:

var list = db.Ads
          .Where(x => x.IsPaid == true || x.IsPaid == null)
          .Where(x=> x.TypeId == 1 || x.TypeId == 2)
          .Where(x=> x.CityId == 1)
          .Where(x=> x.CategoryId == 2)
          .ToList();

Solution 3:[3]

&& has a higher precedence than ||, just like in math. So, effectively your condition is the following:

x.IsPaid == true ||
x.IsPaid == null && x.TypeId == 1 ||
x.TypeId == 2 && x.CityId == 1 && x.CategoryId == 2

If any of those expressions on separate lines are true, the whole expression is true. You have to use parentheses to clarify here:

(x.IsPaid == true || x.IsPaid == null) &&
(x.TypeId == 1 || x.TypeId == 2) &&
 x.CityId == 1 &&
 x.CategoryId == 2

Solution 4:[4]

Try this:

var list = db.Ads.Where (
            (x => x.IsPaid == true || x.IsPaid == null) && 
            (x.TypeId == 1 || x.TypeId == 2) && 
            (x.CityId == 1 && x.CategoryId == 2)
).ToList();

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3
Solution 4 Allan Pereira