Gianpiero
Gianpiero

Reputation: 3547

Linq parser issue?

Well, I am not sure if I am wrong or if the linq parsed mistakes, but the following linq query returns what I DON'T want if I don't use additional parenthesis.

int? userLevel;
Guid? supervisorId;
List<int> levelsIds = new List<int>();
string hierarchyPath;

// init the vars above
// ...

var qry = from f in items
          where userLevel.HasValue
                   ? (f.IsMinLevelIdNull() || (levelsIds.Contains(f.MinLevelId)))
                   : true
                && supervisorId.HasValue
                   ? (f.IsSupervisorIdNull() || (!f.ChildrenVisibility && (f.SupervisorId == supervisorId.Value))
                        || (f.ChildrenVisibility && (hierarchyPath.IndexOf(f.SupervisorId.ToString()) >= 0)))
                   : true
          select f;

The idea here is to run a query in AND between two blocks of conditions 'activated' by the presence of the variables 'userLevel' and 'supervisorId'.

For example, if both userLevel and supervisoId are null the query becomes:

var qry = from f in items
          where true && true
          select f;

Well, this query works well only if I enclose in additional parentheses the 2 trigraphs:

var qry = from f in items
          where (userLevel.HasValue
                       ? (f.IsMinLevelIdNull() || (levelsIds.Contains(f.MinLevelId)))
                       : true)
                 && (supervisorId.HasValue
                       ? (f.IsSupervisorIdNull() || (!f.ChildrenVisibility && (f.SupervisorId == supervisorId.Value))
                       || (f.ChildrenVisibility && (hierarchyPath.IndexOf(f.SupervisorId.ToString()) >= 0)))
                   : true)
          select f;

The question is: why the extra parenthesis are required? My opinion is that there is a problem in the linq parser.

Upvotes: 2

Views: 93

Answers (2)

paul
paul

Reputation: 1279

The additional parentheses would be required as the precedence is evaluated in the wrong order for example your code would be evaluated as the following because there is no break between true && supervisorId.HasValue...

var qry = from f in items  
      where 

        1st: userLevel.HasValue

            ? 

        2nd: (f.IsMinLevelIdNull() || (levelsIds.Contains(f.MinLevelId))) 

            : 

        3rd: true && supervisorId.HasValue  
               ? (f.IsSupervisorIdNull() || (!f.ChildrenVisibility && (f.SupervisorId == supervisorId.Value))  
                    || (f.ChildrenVisibility && (hierarchyPath.IndexOf(f.SupervisorId.ToString()) >= 0)))  **)**
               : true  
      select f; 

Upvotes: 2

Aducci
Aducci

Reputation: 26694

From 7.2.1 Operator precedence and associativity && gets evaluated before ? :

Upvotes: 6

Related Questions