1

Are anonymous methods defined inline ? In the example below, the delegate object "d" is having reference of an anonymous method, which is accessing "x" variable which is defined in the Fun method. The scope of "x" should be limited to Fun method, but when we call MyFun, which invokes the delegate passed as parameter and increments the value of "x".

The output comes out to be "6", how does this happen ? How the value of "x", or in first place "x" variable itself was available in the anonymous method ?

public delegate void Del();

public void Fun()
{
    int x = 5;
    Del d = delegate { x++;  };
    MyFun(d);
    Console.WriteLine(x);
}

public static void MyFun(Del d)
{
    d();
}
Brij
  • 11,731
  • 22
  • 78
  • 116

2 Answers2

6

Are anonymous methods defined inline?

I don't know what "inline" means.

In the example below, the delegate object "d" is having reference of an anonymous method, which is accessing "x" variable which is defined in the Del method.

No, x is defined in the Fun method. Del is not a method, it's a delegate type.

The scope of "x" should be limited to Fun method.

Correct. Recall that "the scope of x" is defined as "the region of program text in which x may be looked up by its unqualified name". You are using the term correctly; the body of Fun is the scope of x. Note that the anonymous method is inside Fun and therefore x is in scope.

when we call MyFun, it invokes the delegate passed as parameter and increments the value of "x".

Correct.

The output comes out to be "6".

Correct.

how does this happen ?

The question is not entirely clear. It sounds like you've already provided an explanation for how this happens: the variable x is in scope inside the anonymous function, the function increments the variable, so the value of the variable changes.

If your question is "what code does the compiler generate in order to make this happen?" the compiler pretends that you wrote something like:

public delegate void Del();

private class Locals
{
    public int x;
    public void AnonymousMethod() { x++; }
}    

public void Fun()
{
    Locals locals = new Locals();
    locals.x = 5;
    Del d = locals.AnonymousMethod;
    MyFun(d);
    Console.WriteLine(locals.x);
}

public static void MyFun(Del d)
{
    d();
}
Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • Eric, this looks to be simple in case of single variable "x". What would the compiler generate when we access "x" and some "y" from some object "z" inside the anonymous method ? This can go crazy depending upon how many variables and object we access inside the anonymous method. – Brij Jun 14 '13 at 16:26
  • 1
    @Brij: This is a question-and-answer site. My advice is that you *ask that question* and someone will answer it. – Eric Lippert Jun 14 '13 at 16:31
  • @Brij: And yes, it can "go crazy" as you say. Things get particularly complicated if you have nested anonymous functions that use the formal parameters of outer functions as captured variables in inner functions. This is one of the trickier bits of the compiler. – Eric Lippert Jun 14 '13 at 16:32
1

This is called Closure. It captures x and uses it as soon as the delegate is executed. It's done through some compiler magic.

It can be confusing sometimes, though. For instance, if you change x after defining the delegate, that change value would be used.

JeffRSon
  • 10,404
  • 4
  • 26
  • 51
  • When does does it capture `x` ? – Brij Jun 14 '13 at 13:59
  • Please use your favorite search engine for details. Apart from that - a reference is captured when the delegate is assigned to d, but a value that is current at the time of execution will be used (see second part of answer). – JeffRSon Jun 14 '13 at 14:02