Linq解析器问题?

时间:2012-03-20 12:35:27

标签: c# linq

那么, 我不确定我是错了还是linq解析了错误,但是如果我不使用额外的括号,则以下linq查询返回我不想要的内容。

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;

这里的想法是通过变量'userLevel'和'supervisorId'的存在,在两个条件块“激活”之间运行查询。

例如,如果userLevel和supervisoId都为null,则查询变为:

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

好吧,只有当我在附加括号中包含2个三字母时,此查询才有效:

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;

问题是:为什么需要额外的括号?我的观点是linq解析器存在问题。

2 个答案:

答案 0 :(得分:6)

来自7.2.1 Operator precedence and associativity &&来自? :

之前的评估

答案 1 :(得分:2)

将需要额外的括号,因为优先级的计算顺序错误,例如,您的代码将被评估为以下因为 true&amp;&amp; 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;