lucidquiet
lucidquiet

Reputation: 6558

What are C# lambda's compiled into? A stackframe, an instance of an anonymous type, or?

What are C# lambda's compiled into? A stackframe, an instance of an anonymous type, or?

I've read this question. Which mostly answers "why" you can't use a lambda when also using implicit type features. But, this question is aimed at answering what construct the compiler produces to actually carry out the code of a lambda. Is it a method call of an anonymous type (something like anonymous types that implement an interface in Java?) or is it just a stack frame with references to closed variables and the accepting the parameter signature? Some lambda's don't close over anything -- so are there then 2 different resulting outputs from the compile.

Upvotes: 15

Views: 2822

Answers (4)

Marc Gravell
Marc Gravell

Reputation: 1062885

Assuming you mean "as a delegate", then it still depends :p if it captures any variables (including "this", which may be implicit) then those variables are actually implemented as fields on a compiler-generated type (not exposed anywhere public), and the statement body becomes a method on that capture class. If there are multiple levels of capture, the outer capture is again a field on the inner capture class. But essentially:

int i = ...
Func<int,int> func = x => 2*x*i;

Is like;

var capture = new SecretType();
capture.i = ...
Func<int,int> func = capture.SecretMethod;

Where:

class SecretType {
    public int i;
    public int SecretMethod(int x) { return 2*x*i; }
}

This is identical to "anonymous methods", but with different syntax.

Note that methods that do not capture state may be implemented as static methods without a capture class.

Expression trees, on the other hand... Are trickier to explain :p

But (I don't have a compiler to hand, so bear with me):

int i = ...
Expression<Func<int,int>> func = x => 2*x*i;

Is something like:

var capture = new SecretType();
capture.i = ...
var p = Expression.Parameter("x", typeof(int));  
Expression<Func<int,int>> func = Expression.Lambda<Func<int,int>>(
    Expression.Multiply(
        Expression.Multiply(Expression.Constant(2),p),
        Expression.PropertyOrField(Expression.Constant(capture), "i")
    ), p);

(except using the non-existent "memberof" construct, since the compiler can cheat)

Expression trees are complex, but can be deconstructed and inspected - for example to translate into TSQL.

Upvotes: 21

Omar
Omar

Reputation: 16623

A lambda expression is an unnamed method written in place of delegate istance. The compiler converts it to either:

  • A delegate instance
  • An expression tree, of type Expression<TDelegate> that representing the code inside, in a traversable object model. This allows the lambda expression to be interpreted at runtime.

So the compiler solves lambda expressions moving the expression's code into a private method.

Upvotes: 1

Michael Liu
Michael Liu

Reputation: 55399

Here are some examples:

public class C
{
    private int field = 0;

    public void M()
    {
        int local = 0;

        Func<int> f1 = () => 0;
        // f1 is a delegate that references a compiler-generated static method in C

        Func<int> f2 = () => this.field;
        // f2 is a delegate that references a compiler-generated instance method in C

        Func<int> f3 = () => local;
        // f3 is a delegate that references an instance method of a compiler-generated nested class in C
    }
}

Upvotes: 1

Travis J
Travis J

Reputation: 82287

Lambda expressions are indeed anonymous functions, but with more versatility. These two articles authored by the MSDN have a lot of information on lambda expressions, how to use them, what precedence the operator => has, what their relation to anonymous functions are, and some advanced suggestions of use.

Lambda Expressions (MSDN)

=> Operator (MSDN)

Upvotes: 1

Related Questions