views:

38

answers:

1

I have a Func defined as follows:

Func<Foo, bool> IsSuperhero = x => x.WearsUnderpantsOutsideTrousers;

I can query IEnumerables like this:

IEnumerable<Foo> foos = GetAllMyFoos();
var superFoos = foos.Where(IsSuperhero);

But when I try to supply the same Func to the Where method of an IQueryable, I get:

'Cannot convert source type System.Collections.Generic.IEnumerable to System.Linq.IQueryable.'

What's going on? How can I define a Func which will work as a specification for both IEnumerable and IQueryable?

+2  A: 

IQueryable's LINQ methods take Expression Trees, not normal delegates.

Therefore, you need to change your func variable to an Expression<Func<Foo, bool>>, like this:

Expression<Func<Foo, bool>> IsSuperhero = x => x.WearsUnderpantsOutsideTrousers;

To use the same variable with an IEnumerable<T>, you'll need to call AsQueryable() or Compile(), like this:

IQueryable<Foo> superFoos = foos.AsQueryable().Where(IsSuperhero);
IEnumerable<Foo> superFoos = foos.Where(IsSuperhero.Compile());
SLaks
But then I can't query IEnumerables with it!!! Surely there must be a way I can use the same specification with both?
David
Oh, and thanks for your answer!
David
Okay, thanks - but what a huge shame for Linq's API.
David
@David: This behavior is necessary. `IQueryable` is meant for things like LINQ to SQL, which need to find out what the delegate does. This is not possible with a normal delegate, so they must take an `Expression<T>`.
SLaks
Wow! I think I'm a long way from understanding that, but thanks for the pointer! :)
David
@David, it's worth learning more about, as expression trees are very, very cool. They encode information about what the expression _means_ rather than simply resulting in code that performs the function. Systems can make good use of this information to do fun, clever things like turning a strongly-typed .NET expression into a standard SQL query.
Dan Bryant
Thanks for that. I'm aware that they are used to convert a set of criteria into another form (e.g. a SQL or LDAP query), but way in which this is done is, for me, in a distant, misty land full of magic. But that may not always be the case!
David
Thanks everyone for your input. This has been a very educational post for me.
David