Search code examples
c#lambdaexpressionfunc

Why can not be Func casted to Expression, but lambda can


In the example below, the same lambda can be hold as an Expression in test but it fails to compile when it comes form a Func:

Func<int> func = () => 2;
Expression test1 = (Expression<Func<int>>)(() => 2);
Expression test2 = (Expression<Func<int>>)(func); //does not compile

Why a lambda can be converted to an Expression directly, but not when it is represented as a Func?


Solution

  • A Func<int> is a delegate instance - an instance of an object; it no longer has any semantic state other than "this target object reference, this method handle".

    An expression tree is something much richer; it is a complex graph of the intent of code - essentially an AST. You can compile an expression to a delegate instance, but you cannot reverse a delegate to an expression tree.

    When you do:

    Expression<Func<int>> func = () => 2;
    

    you are creating a complex tree; essentially:

    var func = Expression.Lambda<Func<int>>(Expression.Constant(2, typeof(int)),
        Array.Empty<ParameterExpression>());
    

    (but much more complex in the general case, obviously)