【问题标题】:Operator '||' cannot be applied to operands of type 'lambda expression' and 'lambda expression'运算符“||”不能应用于“lambda 表达式”和“lambda 表达式”类型的操作数
【发布时间】:2012-01-17 19:00:14
【问题描述】:

如何构造一个包含OR 的LINQ WHERE 子句?


我有一个对象列表,我想返回符合搜索条件的对象。

包含的对象有很多属性,只要 any 符合条件,我想返回它:

IEnumerable<Item> list;
String keyword; 
...

var results = list.Where(
      (item => item.Name.Contains(keyword, StringComparison.CurrentCultureIgnoreCase))
      ||
      (item => item.Description.Contains(keyword, StringComparison.CurrentCultureIgnoreCase))
      ||
      (item => item.Description.Contains(keyword, StringComparison.CurrentCultureIgnoreCase))
      ||
      (item => item.ItemType.Contains(keyword, StringComparison.CurrentCultureIgnoreCase))
      ||
      (item => item.ItemID.ToString().StartsWith(keyword, StringComparison.CurrentCultureIgnoreCase))
      ||
      (items => items.Value.ToString().StartsWith(keyword, StringComparison.CurrentCultureIgnoreCase))
);

但是编译失败:

运算符“||”不能应用于“lambda 表达式”和“lambda 表达式”类型的操作数

如何构造一个包含OR 的LINQ WHERE 子句?

另见

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    只需在同一个 lambda 表达式中进行所有测试...

    IEnumerable<Item> list;
    String keyword; 
    ...
    
    var results = list.Where(
          item => item.Name.Contains(keyword, StringComparison.CurrentCultureIgnoreCase)
          || item.Description.Contains(keyword, StringComparison.CurrentCultureIgnoreCase)
          || item.Description.Contains(keyword, StringComparison.CurrentCultureIgnoreCase)
          || item.ItemType.Contains(keyword, StringComparison.CurrentCultureIgnoreCase)
          || item.ItemID.ToString().StartsWith(keyword, StringComparison.CurrentCultureIgnoreCase)
          || items.Value.ToString().StartsWith(keyword, StringComparison.CurrentCultureIgnoreCase)
    );
    

    【讨论】:

    • 我很好奇为什么这个答案得到了 6 个赞,而其他三个基本相同的答案却没有得到任何支持,尤其是因为这是添加的最新答案。
    • 你说得对,我对“x 分钟前”含义的理解倒退了。
    • @EsotericScreenName 我还要说它得到了我的支持并接受,因为他花时间从源代码中复制粘贴修复整个示例(并且格式很好)。额外的工作得到额外的爱。
    • @IanBoyd:它由各种拼写错误组成:items 而不是item,重复了item.Description.Contains... 子句。
    【解决方案2】:

    您试图在不正确的单独 lambda 表达式中表达每个条件。

    您希望将所有表达式都包含在单个 lambda 表达式中:

    var results = list.Where(item =>
        (item.Name.Contains(keyword, StringComparison.CurrentCultureIgnoreCase))
        || (item.Description.Contains(keyword, StringComparison.CurrentCultureIgnoreCase))
        || (item.Description.Contains(keyword, StringComparison.CurrentCultureIgnoreCase))
        // and so on
    );
    

    【讨论】:

      【解决方案3】:

      只是一种我认为有趣的不同方法;如果需要,它可以提供更可组合的解决方案。您可以使用为 linq-to-objects 修改的 Predicate Builder 版本。像这样:

      var predicate = DelegatePredicateBuilder.False<Item>();
      
      predicate.Or (x => x.Name.Contains(keyword))
               .Or (x => x.Description.Contains(keyword))
               .Or (x => x.ItemID.ToString().StartsWith(keyword))
               .Or (...); // etc
      
      var results = list.Where(predicate);
      

      我已经删减了一些样板代码,只是为了展示这个想法的要点。

      linq-to-objects predicate builder 来自 Jon Skeet 的回答。为了完整起见,此处发布的代码:

      public static class DelegatePredicateBuilder
      {
        public static Func<T, bool> True<T>()  { return f => true;  }
        public static Func<T, bool> False<T>() { return f => false; }
      
        public static Func<T, bool> Or<T>(this Func<T, bool> expr1,
                                       Func<T, bool> expr2)
        {
          return t => expr1(t) || expr2(t);
        }
      
        public static Func<T, bool> And<T>(this Func<T, bool> expr1,
                                                Func<T, bool> expr2)
        {
         return t => expr1(t) && expr2(t);
        }
      }
      

      【讨论】:

      • 这看起来非常有用;虽然我不知道我在看什么。 C# 确实开始将 Java 的超快速度与 perl 的优雅可读性结合起来。
      • @IanBoyd 几年前我第一次看到谓词构建器的源代码。直到今天,我仍然需要看到它曾经理解它。
      【解决方案4】:

      您不能组合多个 lambda,您想基于 where 子句中条件的 or (||) 组合构建布尔表达式:

      var results = list.Where( item => item.Name.Contains(keyword, StringComparison.CurrentCultureIgnoreCase))
                                || item.Description.Contains(keyword, StringComparison.CurrentCultureIgnoreCase))
      

      【讨论】:

        【解决方案5】:

        尝试在每次比较时删除 lambda 声明...类似于:

        var 结果 = list.Where( (item => item.Name.Contains(keyword, StringComparison.CurrentCultureIgnoreCase) || item.Description.Contains(关键字,StringComparison.CurrentCultureIgnoreCase) || item.Description.Contains(关键字,StringComparison.CurrentCultureIgnoreCase) || item.ItemType.Contains(关键字,StringComparison.CurrentCultureIgnoreCase) || item.ItemID.ToString().StartsWith(keyword, StringComparison.CurrentCultureIgnoreCase) || items.Value.ToString().StartsWith(keyword, StringComparison.CurrentCultureIgnoreCase) );

        【讨论】:

          猜你喜欢
          • 2011-10-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-03-14
          • 2016-06-14
          • 1970-01-01
          • 2014-06-21
          • 1970-01-01
          相关资源
          最近更新 更多