Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does an Expression type in .NET allows construction from a function but not conversion from one?

Why does expr1 compile but not expr2?

Func<object> func = () => new object();
Expression<Func<object>> expr1 = () => new object();
Expression<Func<object>> expr2 = func; //Cannot implicitly convert type 'System.Func<object>' to 'System.Linq.Expressions.Expression<System.Func<object>>'
like image 354
Christian Avatar asked Jan 12 '13 20:01

Christian


3 Answers

A Func<T> is a delegate (a pointer to a function), while an Expression<Func<T>> is an expression tree (a tree-like data structure that describes an operation). It follows that you cannot assign one to the other, as they are completely dissimilar.

When you assign a lambda function directly to a Func<T> the compiler compiles the code for your function and assigns a pointer to the compiled code to e.g. func.

On the other hand, when you assign a lambda function directly to an Expression<Func<T>> the compiler builds up the expression tree (which is simply an instance of a reference type) and assigns a reference to that object to e.g. expr1. This is just a convenience that the compiler provides to you, giving you a much more attractive option than manually constructing the expression tree yourself in code (which of course is also completely possible).

like image 75
Jon Avatar answered Nov 15 '22 01:11

Jon


You cannot convert between Func and Expression types. But you can convert from a lambda to either of them.

A lambda has a special type that only exists in the C# type system. The CLR does not know what a lambda is. Only the C# compiler knows that and the only operations that you can do with a lambda is to convert to the Func and Expression types. (This means that you cannot invoke a lambda for example as it has no CLR type at all).

That is why you observe a "semantic gap" here.

like image 33
usr Avatar answered Nov 15 '22 01:11

usr


In simpler words the compiler can convert a chunk of code (Lambda expression) into

  • an Expression
  • or a Func

This happens immediately when used, then the code is gone, converted non-reversible. But Func and Expression are completely different types.

That's why you can't

Expression<Func<object>> expr2 = func;

But the other way around would work with

Func<object> func2 = expr1.Compile();
like image 2
Desty Avatar answered Nov 15 '22 00:11

Desty