17

I am trying to create a method where I can pass a Linq expression as a parameter to return a new list of items.

Currently I am doing this (based off this answer):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

class Collection<T> {

    List<T> items = new List<T>();

    public Collection<T> Filter(Expression<Func<T, bool>> query) {
        Collection<T> c = new Collection<T>();
        c = items.Where(query);
        return c;
    }
}

'List' does not contain a definition for 'Where' and the best extension method overload 'Queryable.Where(IQueryable, Expression>)' requires a receiver of type 'IQueryable'

I am not exactly sure what to do here to fix this.

Community
  • 1
  • 1
Get Off My Lawn
  • 34,175
  • 38
  • 176
  • 338
  • For [Where](https://msdn.microsoft.com/en-us/library/bb534803(v=vs.110).aspx) you need to pass it a `Func` which is not what your `query` is. – Matt Burland Nov 30 '16 at 18:25
  • When you do `c = items.Where(query);`, you are not filling the collection but (trying to) create a new one. See Rene Vogt's answer for a solution. – Hans Kesting Nov 30 '16 at 18:32

2 Answers2

12

List<T> is not IQueryable<T> but IEnumerable<T>. For the Where extension for IEnumerable<T> you can only pass a delegate not an expression.

I guess you want something like that:

public Collection<T> Filter(Func<T, bool> query) // only the lambda, NO expression
{
    Collection<T> c = new Collection<T>(items.Where(query).ToList());
    return c;
}

Note that Where only returns an IEnumerable<T> but not an Collection<T>. So you need to convert c to a List<T> and pass this to the constructor of Collection<T>.

René Vogt
  • 43,056
  • 14
  • 77
  • 99
2

If you absolutely must use an expression, there are a couple of things you could do. You can do something like this:

public ICollection<T> Filter(Expression<Func<T, bool>> query) {     
    return items.AsQueryable().Where(query).ToList();
}

Converting you IList to a Queryable or you could do this:

public ICollection<T> Filter(Expression<Func<T, bool>> query) {     
    return items.Where(query.Compile()).ToList();
}

Compiling your expression to a Func<T, bool>

Matt Burland
  • 44,552
  • 18
  • 99
  • 171