Reputation: 1998
From C# in depth:
Not all lambda expressions can be converted to expression trees. You can’t convert a lambda with a block of statements ( even just one return statement ) into an expresion tree --> it has to be in the form that just evaluates a single expression.
Since Linq-to-Object statements don't get converted into expression tree objects, the lambda expressions used with Linq-to-Object operators can contain a block of statements
string[] count = { "one ", "two ", "three ", "four ", "five ", "six " };
IEnumerable<int> result = count.Select(item =>
{
Console.WriteLine(item);
return item.Length;
});
foreach (int i in result);
OUTPUT:
one two three four five six
I haven't yet started learning Linq-To-Sql or Linq-To-Entities, but I assume lambda expressions used with LINQ statements that operate on IQueryable<T>
can only ever contain a single expression, due to restristion that only a single expression can be converted into an expression tree?
Thank you
Upvotes: 8
Views: 16642
Reputation: 23613
You are correct, they can only ever contain a single expression.
Upvotes: 1
Reputation: 1503290
It's not just that they can only contain a single expression - it's can't be a statement lambda at all. Even a block like this:
var result = query.Select(item => { return item.Length; });
would be invalid for LINQ to SQL. It would have to be expressed as:
var result = query.Select(item => item.Length);
(I've just noticed that that's the bit of the book you quoted. Oh well - it shows I'm consistent :)
Note that as of .NET 4, expression trees themselves do have the ability to contain blocks, but the C# compiler can't translate statement lambdas into that kind of expression tree. There are other restrictions too, but they rarely cause problems.
This is specified in section 4.6 of the C# 4 spec:
Not all anonymous functions can be represented as expression trees. For instance, anonymous functions with statement bodies and anonymous functions containing assignment expressions cannot be represented. In these cases, a conversion still exists, but will fail at compile-time.
Upvotes: 18