Operator '||' cannot be applied to operands of type 'lambda expression' and 'lambda expression'

How do i construct a LINQ WHERE clause that contains OR?


i have a list of objects, and i want to return those that match a search criteria.

The contained objects have many properties, and as long as any match the criteria, i want to return it:

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))
);

But that fails to compile:

Operator '||' cannot be applied to operands of type 'lambda expression' and 'lambda expression'

How do i construct a LINQ WHERE clause that contains OR?

See also

  • LINQ where or filter c#

Just do all your tests in the same lambda expression...

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)
);

You're trying to express each condition inside of a separate lambda expression which is incorrect.

You want to have all of your expressions inside of a single lambda expression:

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
);

Just a different approach which I think is interesting; it allows a more composable solution if you want it. You can use a version of Predicate Builder modified for linq-to-objects. Like this:

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);

I've trimmed some of the boilerplate code to just show the gist of the idea.

The linq-to-objects predicate builder is from an answer by Jon Skeet. Code posted here for completeness:

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);
  }
}