Сохраняет ли встроенный код метод [который написал в нем] в памяти после завершения выполнения? - PullRequest
2 голосов
/ 19 июня 2010

В зависимости от того, что я знаю, когда я определяю метод в C #, локальные переменные в этом методе будут освобождены из памяти после завершения выполнения блока этого метода [когда GC хочет],

но если у меня есть встроенный обратный вызов в методе, будут ли эти локальные переменные также освобождены из памяти?

В следующем примере переменная [x] сохранит свое значение после завершения выполнения методаи сообщение покажет значение [x] без проблем, хотя оно находится в обратном вызове !!

    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();
    }

1 Ответ

5 голосов
/ 19 июня 2010

Переменная 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), но как только вы удалите таймер, закрытие также будет собирать мусор.

ЭтоСтоит отметить, что компилятор захватывает те локальные переменные, которые фактически используются в лямбда-функции (поэтому, если у вас есть большие данные в методе, они не будут случайно поддерживаться дольше, чем нужно).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...