Search code examples
c#linqternary

Linq where with ternary and brackets


I have the following query:

return Postcodes
            .Where(
                s => s.Postcode.IndexOf(term, StringComparison.InvariantCultureIgnoreCase) > -1 &&
                string.IsNullOrEmpty(country) ? true : s.CountryRegionID.Equals(country, StringComparison.InvariantCultureIgnoreCase)
            )
            .Select(p => new { label = p.Postcode, value = p.RecID })
            .ToList();

Now I would have expected this to return all postcodes matching both country and term but for some reason it only matches the term if the country is null and then if the country isn't null, it ignores the term and just matches the country.

If I put brackets around the ternary:

return Postcodes
            .Where(
                s => s.Postcode.IndexOf(term, StringComparison.InvariantCultureIgnoreCase) > -1 &&
                (string.IsNullOrEmpty(country) ? true : s.CountryRegionID.Equals(country, StringComparison.InvariantCultureIgnoreCase))
            )
            .Select(p => new { label = p.Postcode, value = p.RecID })
            .ToList();

Then it works exactly as I would expect. Why does the extra pair of brackets make a difference as code analysis always complains about me putting brackets around ternaries?


Solution

  • In C# ternary operator has lower priority than conditional AND operator. Thus without brackets AND evaluated before ternary operator and you have ternary operator which checks postcode AND country. I.e. by default

    ( checkPostcode && countryNotNull) ? true : checkCountry
    

    When you add brackets you split ternary operator which checks country from postcode check

    checkPostcode && (countryNotNull ? true : checkCountry)
    

    See 7.2.1 Operator precedence and associativity