0

In Java, modifying a local variable like this would result in:

Local variable i defined in an enclosing scope must be final or effectively final

However, the same code translated into c# works as expected

int i = 0;

Timer timer = new Timer(1);
timer.Elapsed += (source, arg) => {
    i++;
};
timer.AutoReset = false;
timer.Enabled = true;

Console.WriteLine(i);
System.Threading.Thread.Sleep(100);
Console.WriteLine(i);

0

1

How does this work, and how is it different than the same code in Java? How does the Garbage Collector know when to dispose of variables such as i?

Community
  • 1
  • 1
nathanfranke
  • 775
  • 1
  • 9
  • 19
  • The Garbage Collector does not handle local variables at all. The stack frame containing local variables will always be destroyed when the method exits. The trick works the same way as the dirty work-around in Java, replace the local variable by an object having a field of that type, except that the compiler does that for you behind the scenes. – Holger Jun 13 '19 at 13:38

2 Answers2

3

In c#, closures close over variables not values. The lambda keeps a reference to i rather than the value. External changes to i are visible to the lambda and vice-versa.

This answer may help https://stackoverflow.com/a/22412790/235354

jspcal
  • 50,847
  • 7
  • 72
  • 76
3

It does it through a closure

A closure is a block of code which can be executed at a later time, but which keeps and maintains the environment in which it was first created via the use of a compiler generated class. it can still use the local variables even when the method has finished, the garbage collector maintain reference counts to anything it needs and nothing gets collected which shouldn't be

TheGeneral
  • 79,002
  • 9
  • 103
  • 141