运营商'||'不能应用于'lambda expression'和'lambda expression'类型的操作数

时间:2012-01-17 19:00:14

标签: c# linq

如何构造包含WHERE

的LINQ OR子句

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

包含的对象有很多属性,只要 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 expression'和'lambda expression'

类型的操作数

如何构造包含WHERE

的LINQ OR子句

另见

5 个答案:

答案 0 :(得分:16)

只需在同一个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)
);

答案 1 :(得分:3)

您试图在单独的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
);

答案 2 :(得分: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);
  }
}

答案 3 :(得分:1)

你不能组合多个lambda,你想根据||子句中条件的(或where)组合构建一个布尔表达式:

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

答案 4 :(得分:1)

尝试在每次比较时删除lambda声明......如:

  

var results = list.Where(         (item =&gt; 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));