Expression tree limitations in C# 3.0
September 7th, 2007
Everything in this article is tested with Visual Studio 2008 Beta 2 and may become obsolete.
While a lot of people blog about expression trees in new C#, I haven’t seen any post about things you can not do with them. Maybe it is common knowledge, but since I stumbled in it myself, I’ll share.
Basically, C# specification says:
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.
So, that’s what you can not do according to the specification:
Expression<…> y = x => { DoAnything() }; // error CS0834: A lambda expression with a statement body cannot be converted to an expression tree int z = 3; Expression<…> y = () => z = z + 5; // error CS0832: An expression tree may not contain an assignment operator.
To find out other limitations, I’ve looked in Microsoft.NET\Framework\v3.5\1033\cscompui.dll file (that contains all string resources (errors/warnings) for csc compiler) and did a search on “expression tree”.
So there is a summary table of all compiler errors on expression trees with sample code for each case:
Error code | Error message | Sample code |
---|---|---|
CS???? | Partial methods with only a defining declaration or removed conditional methods cannot be used in expression trees. | I see no way to use partial in expression tree. Partial methods always return void, so they can be used only as a statement and not in a lambda with expression body. |
CS0831 | An expression tree may not contain a base access. |
Expression<Func<string>> y = () => base.ToString(); |
CS0832 | An expression tree may not contain an assignment operator. | See above. |
CS0834 | A lambda expression with a statement body cannot be converted to an expression tree. | See above. |
CS0838 | An expression tree may not contain a multidimensional array initializer. |
Expression<Func<string[,]>> y = () => new string[,] { { "A", "A"} }; |
CS0838 | An expression tree may not contain an unsafe pointer operation. | No sample, I am not very friendly with unsafe syntax. |
CS1945 | An expression tree may not contain an anonymous method expression. |
Expression<Func<Func<string>>> y = () => delegate { return "hi"; }; // [NB] This woks just fine: Expression<Func<Func<string>>> y = () => () => "hi"; |
CS1952 | An expression tree lambda may not contain a method with variable arguments. | This one was tricky:
public string ReturnHi(__arglist) { return "hi"; } public void Test() { Expression<Func<string>> y = () => this.ReturnHi(__arglist("stub1", "stub2")); } |
There are several error messages other than the first one in a table that I can not produce at all.
Error message | Comment |
---|---|
An expression tree lambda may not contain an out or ref parameter. | Lambdas indeed can not capture out and ref parameters, but the error in such case is CS1628: Cannot use ref or out parameter ‘…’ inside an anonymous method, lambda expression, or query expression. I could not create any kind of lambda for the delegate type with out or ref parameter, not only expression tree. |
An expression tree lambda may not contain a member group. | No problems creating lambdas that do any member group resolution. I have no idea how to put unresolved member group anywhere without getting it resolved. |