Переменная x
фиксируется в замыкании, связанном с лямбда-функцией.Это означает, что значение x
на самом деле хранится не в стеке, связанном с исключением MyMethod
, а в куче (в объекте, на который ссылается лямбда-функция).
В следующем примере показано(примерно), как компилятор C # преобразует код:
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();
}
Как видите, переменная x
теперь хранится в объекте, выделенном в куче (называемом замыканием).Объект будет живым до тех пор, пока таймер может вызывать метод (и до тех пор, пока можно получить доступ к x
), но как только вы удалите таймер, закрытие также будет собирать мусор.
ЭтоСтоит отметить, что компилятор захватывает те локальные переменные, которые фактически используются в лямбда-функции (поэтому, если у вас есть большие данные в методе, они не будут случайно поддерживаться дольше, чем нужно).