Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does Lambda Expression Compile() method do?

I am trying to understand AST in C#. I wonder, what exactly Compile() method from this example does.

// Some code skipped     Expression<Func<string, int, int, string>> data = Expression.Lambda<Func<string, int, int, string>>(          Expression.Call(s, typeof(string).GetMethod(“Substring”, new Type[] { typeof(int), typeof(int) }), a, b),          s, a, b      );  Func<string, int, int, string> fun = data.Compile();  

To prevent misunderstandings, I understand the Expression.Lambda and Expression.Call constructs. What interests me is the Compile() method. Does it somehow produce real MSIL? Can I see the MSIL?

like image 572
jk_ Avatar asked Nov 14 '11 19:11

jk_


People also ask

What happens with lambda after Compile time?

For Lambda expressions, the compiler doesn't translate them into something which is already understood by JVM. Lambda syntax that is written by the developer is desugared into JVM level instructions generated during compilation, which means the actual responsibility of constructing lambda is deferred to runtime.

How do you execute an expression?

Only expression trees that represent lambda expressions can be executed. Expression trees that represent lambda expressions are of type LambdaExpression or Expression<TDelegate>. To execute these expression trees, call the Compile method to create an executable delegate, and then invoke the delegate.

What is lambda expression in LINQ?

The term 'Lambda expression' has derived its name from 'lambda' calculus which in turn is a mathematical notation applied for defining functions. Lambda expressions as a LINQ equation's executable part translate logic in a way at run time so it can pass on to the data source conveniently.

How do you use expression lambda?

To create a lambda expression, you specify input parameters (if any) on the left side of the lambda operator and an expression or a statement block on the other side. When you use method-based syntax to call the Enumerable. Select method in the System.


2 Answers

What interests me is the Compile() method. Does it somehow produce real MSIL?

Yes. The Compile method runs a visitor over the lambda body block and generates IL dynamically for each subexpression.

If you're interested in learning how to spit IL yourself, see this "Hello World" example of how to use Lightweight Codegen. (I note that if you are in the unfortunate position of having to use Lightweight Codegen in a partially trusted appdomain then things can get a bit weird in a world with Restricted Skip Visibility; see Shawn Farkas's article on the subject if that interests you.)

Can I see the MSIL?

Yes, but you need a special "visualizer". The visualizer I used to debug Compile() while I was implementing my portions of it can be downloaded here:

http://blogs.msdn.com/b/haibo_luo/archive/2005/10/25/484861.aspx

like image 185
Eric Lippert Avatar answered Sep 19 '22 21:09

Eric Lippert


The answer to this is now partly outdated, in that it's now only sometimes what happens.

Compilation of expressions to IL requires Reflection.Emit which isn't available all the time, particular with AOT. So in those cases instead of compiling to IL the expression is "compiled" to a list of objects representing instructions. Each of these instructions has a Run method that causes it to carry out the appropriate action, working on a stack of values much as IL works on a stack. A method that calls Run on these objects can then be returned as the delegate.

Generally running such a delegate is slower than jitting IL, but it's the only option when compiling to IL isn't available, and the compilation step is often faster, so very often the total time of compile + run is less with the interpreter than with IL for one-off expressions.

For that reason, in .NET Core there is now an overload of Compile that takes a boolean requesting interpretation even if compiling to IL is available.

All of which makes for an interesting mix of languages; Expressions themselves are a language, the assembly is written in C#, it can compile to IL and the interpreted instruction objects constitute a fourth language.

like image 28
Jon Hanna Avatar answered Sep 18 '22 21:09

Jon Hanna