tags:

views:

56

answers:

1

Hi all,

Depending on what I know, when I define a method in C#, the local variables in this method will be released from memory after finishing executing the block of this method [when GC wants],

but if I have an inline callback in a method, will these local variables be released from memory also ?

In the following example, the [x] variable will keep its value after finishing executing the method and the message will show the value of [x] without problem although it's in a callback !!

    private void MyMethod()
    {
        int x = 1;
        System.Timers.Timer t = new System.Timers.Timer(1000);
        t.Elapsed += (sender, e) => MessageBox.Show((x++).ToString()); ;
        t.Start();
    }
+7  A: 

The variable x is captured in a closure associated with the lambda function. This means that the value of x isn't actually stored on the stack associated with the exection of MyMethod but on the heap (in an object referenced from the lambda function).

The following example shows (roughly) how the C# compiler transforms the code:

class $$MyMethod$$Closure { 
  public int x;
  void Function(object sender, EventArgs e) {
    MessageBox.Show((x++).ToString());
  }
}

private void MyMethod() {
    var $$closure = new $$MyMethod$$Closure();
    $$closure.x = 1; 
    System.Timers.Timer t = new System.Timers.Timer(1000); 
    t.Elapsed += $$closure.LambdaFunction; 
    t.Start(); 
}

As you can see, the x variable is now stored in an heap-allocated object (called closure). The object will be alive as long as the timer can call the method (and as long as x can be accessed), but once you remove the timer, the closure will be also garbage collected.

It is worth noting that the compiler only captures those local variables that are actually used in the lambda function (so if you have some large data in the method, they won't be accidentally kept alive longer than needed).

Tomas Petricek