Converting lambda expression into an expression tree

15,787

Solution 1

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.

Solution 2

You are correct, they can only ever contain a single expression.

Share:
15,787
AspOnMyNet
Author by

AspOnMyNet

Updated on June 13, 2022

Comments

  • AspOnMyNet
    AspOnMyNet almost 2 years

    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

  • Patrick Karcher
    Patrick Karcher over 12 years
    Now, what on earth would you know about something mentioned in C# in Depth? Oh, never mind.
  • AspOnMyNet
    AspOnMyNet over 12 years
    @Jon: It suddenly occurred to me how very related this question is to that at stackoverflow.com/questions/8405423/… wink wink
  • Nick
    Nick over 9 years
    Jon, what do you mean when you say it can't be a statement lambda? The question shows sample code using a statement lambda and it outputs the correct values.
  • Jon Skeet
    Jon Skeet over 9 years
    @Nick: It uses a statement lambda... But converts it into a delegate, not an expression tree.
  • Azri Jamil
    Azri Jamil over 7 years
    Expression tree does not execute code rather than generating data, where later you can compile it back to code.
  • Jon Skeet
    Jon Skeet over 7 years
    @wajatimur: I'm not entirely sure what the point of your comment was... could you clarify?