Can't initialize LambdaExpression with an expression

c# expression-trees lambda

Question

Question similar to one by John K, but more specific and the accepted answer doesn't suit my needs.

This compiles fine:

Expression<Func<object, object>> specificExpression = (object o) => new object();
Expression generalExpression = specificExpression;

And this one doesn't:

Expression generalExpression = (object o) => new object();

Reported compile error:

Cannot convert lambda expression to type 'System.Linq.Expressions.Expression' because it is not a delegate type

Expression<Func<T1,T2>> derives from Expression.

Now I have a framework with methods accepting all sorts of expressions, i.e. type Expression. Being forced to explicitly cast lambdas to the corresponding Expression<Func<T1,T2>> on each method call is frustrating.

Any good reasons why this basic OOP behavior is broken in this case?

Accepted Answer

The conversion doesn't work because the compiler cannot infer which specific expression type you are trying to create. What if you did this?

Expression generalExpression = (object o) => "foo";

Should this be an Expression<Func<object, string>>? What about Expression<Func<object, object>> or Expression<Func<object, IComparable>>? These types would all be a valid final type for the expression tree, and the compiler doesn't pretend to know what you are trying to do.

You need to cast through the specific type to inform the compiler which type of expression you want to produce:

Expression generalExpression = (Expression<Func<object, object>>)
    (object o) => new object();

You would see a similar compiler error if you tried this:

Delegate generalDelegate = delegate() { };

Is that an Action, or a ThreadStart, or some other kind of no-argument void-returning delegate?


Popular Answer

The C# compiler evaluates the expression to the least complex form, for example:

 var x = (object o) => new object();

x should be a Func<object, object>, not an Expression<Func<object, object>>. In this case, the compiler is determining the value is a delegate, and since Expression cannot take a delegate (only the Expression<Func<>> / Expression<Action> types can), the compiler error is thrown.

Also, see @Riana's answer, because the expression form is actuall rewritten by the compiler.




Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why