How to create an Expression<Func<dynamic, dynamic>> - Or is it a bug?

.net-4.0, c#, dynamic, expression-trees, lambda

Solution

I suppose that, under the hood, the expression returned by ConvertExpression is perhaps of type `Expression<Func<object, object>>`, which is a valid type

Correct.

I can't use `Expression<Func<dynamic, dynamic>>` type in a declaration and yet I can use it as the return type of a method.

This portion of the statement is incorrect. As you note in your example, it is perfectly legal to use that type in the declaration of a local variable.

The bit that is not legal is the execution of a dynamic operation inside a lambda that is being converted to an expression tree type. The specific expression tree type is irrelevant; what matters is that the operation is dynamic.

Problem

During my work with expression trees for a few days now, I came across something that I find difficult to understand; hopefully someone will be able so shed some light here. If you code `Expression<Func<dynamic, dynamic>> expr1 = x => 2 * x;` the compiler will complain and you won't get anywhere. However, it seems that if you create one such expression through a method then the compiler seems to be happy about it and the resulting app works. This doesn't make sense, so I'm wondering what goes on behind the curtains. I suppose that, under the hood, the expression returned by `ConvertExpression` is perhaps of type `Expression<Func<object, object>>`, which is a valid type, but it puzzles me that I can't use `Expression<Func<dynamic, dynamic>>` type in a declaration and yet I can use it as the return type of a method. See an example below. Thanks a lot! ``` public class ExpressionExample { public void Main() { // Doesn't compile: //Expression<Func<dynamic, dynamic>> expr1 = x => 2 * x; // Compiles and works - OK Expression<Func<double, double>> expr2 = x => 2 * x; Func<double, double> func2 = (Func<double, double>)expr2.Compile(); Console.WriteLine(func2(5.0).ToString()); // Outputs 10 // Compiles and works - ??? This is the confusing block... Expression<Func<dynamic, dynamic>> expr3 = ConvertExpression(expr2); Func<dynamic, dynamic> func3 = (Func<dynamic, dynamic>)expr3.Compile(); Console.WriteLine(func3(5.0).ToString()); // Outputs 10 // Side note: compiles and works: Expression<Func<object, object>> expr4 = x => double.Parse(2.ToString()) * double.Parse(x.ToString()); Func<object, object> func4 = (Func<object, object>)expr4.Compile(); Console.WriteLine(func4(5.0).ToString()); // Outputs 10 } private Expression<Func<dynamic, dynamic>> ConvertExpression<TInput, TOutput>(Expression<Func<TInput, TOutput>> expression) { Expression<Func<object, TInput>> convertToInput = value => (TInput)value; // The following doesn't compile: var input = Expression.Parameter(typeof(dynamic), "input"); var input = Expression.Parameter(typeof(object), "input"); Expression<Func<TOutput, dynamic>> convertToOutput = value => (dynamic)value; var body = Expression.Invoke(convertToOutput, Expression.Invoke(expression, Expression.Invoke(convertToInput, input))); var lambda = Expression.Lambda<Func<dynamic, dynamic>>(body, input); return lambda; } } ```

Original source

Related problems