Linq where keyword vs. Where extension and Expression parameters

delegates, extension-methods, linq

Solution

The syntax for a query expression involving a `where` clause is (simplifying the complete grammar)

from identifier in expression where boolean-expression select expression

`whereClause` is not a boolean expression. To recitify this, you have to say

from c in _ctx.Companies where whereClause.Compile()(c) select c;

Note that if `whereClause` were a `Func<Company, bool>` you could get away with

from c in _ctx.Companies where whereClause(c) select c;

Note that

from x in e where f

is translated mechanically by the compiler into

(from x in e).Where(x => f)

I say mechanically because it performs this translation without doing any semantic analysis to check validity of the method calls etc. That stage comes later after all query expressions have been translated to LINQ method-invocation expressions.

In particular,

from c in _ctx.Companies where whereClause select c

is translated to

_ctx.Companies.Where(c => whereClause).Select(c)

which is clearly nonsensical.

The reason that

from c in _ctx.Companies.Where(whereClause) select c

is legit is because `IEnumerable<Company>.Where` has an overload accepting a `Func<Company, bool>` and there is an implicit conversion from an `Expression<Func<Company, bool>>` to a `Func<Company, bool>`.

Problem

Passing in an Expression to a Linq query behaves differently depending on syntax used, and I wonder why this is the case. Let's say I have this very generic function ``` private IEnumerable<Company> GetCompanies(Expression<Func<Company, bool>> whereClause) ``` The following implementation works as expected ``` private IEnumerable<Company> GetCompanies(Expression<Func<Company, bool>> whereClause) { return (from c in _ctx.Companies.Where(whereClause) select c); } ``` But this next implementation does not compile (Delegate 'System.Func' does not take 1 arguments) ``` private IEnumerable<Company> GetCompanies(Expression<Func<Company, bool>> whereClause) { return (from c in _ctx.Companies where whereClause select c); } ``` Obviously I can just use the first syntax, but I was just wondering why the compiler does not treat the where keyword the same as the Where extension? Thanks, Thomas

Original source