Search code examples
c#lambdaexpression-trees

Can't initialize LambdaExpression with an expression


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?


Solution

  • 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?