Как закрытия выполняют незаметную работу? (C#)

Я чувствую, что у меня есть довольно достойное понимание закрытий, как использовать их, и когда они могут быть полезными. Но то, что я не понимаю, - то, как они на самом деле выполняют незаметную работу в памяти. Некоторый пример кода:

public Action Counter()
{
    int count = 0;
    Action counter = () =>
    {
        count++;
    };

    return counter;
}

Обычно, если бы {количество} не было получено закрытием, то его жизненный цикл был бы ограничен по объему к Счетчику () метод, и после того, как это завершается, это ушло бы с остальной частью выделения стека для Счетчика (). Что происходит хотя, когда это закрывается? Целое складывает выделение для этого вызова Счетчика (), слоняются поблизости? Это копирует {рассчитывают} к "куче"? Это на самом деле никогда не становится выделенным на стеке, но распознанным компилятором, как закрываемым, и поэтому всегда живет на "куче"?

Для этого конкретного вопроса я, прежде всего, интересуюсь тем, как это работает в C#, но не было бы настроено против сравнений с другими языками та поддержка закрытия.

45
задан Matt 18 December 2009 в 14:47
поделиться

2 ответа

Компилятор (в отличие от среды выполнения) создает другой класс / тип. Функция с вашим закрытием и любые переменные, которые вы закрыли / подняли / захватили, переписываются во всем вашем коде как члены этого класса. Замыкание в .Net реализовано как один экземпляр этого скрытого класса.

Это означает, что ваша переменная count полностью является членом другого класса, и время жизни этого класса работает как любой другой объект clr; он не подлежит сборке мусора, пока не перестанет быть внедренным. Это означает, что пока у вас есть вызываемая ссылка на метод, он никуда не денется.

33
ответ дан 26 November 2019 в 21:17
поделиться

Ваша третья догадка верна. Компилятор сгенерирует такой код:

private class Locals
{
  public int count;
  public void Anonymous()
  {
    this.count++;
  }
}

public Action Counter()
{
  Locals locals = new Locals();
  locals.count = 0;
  Action counter = new Action(locals.Anonymous);
  return counter;
}

Имеет смысл?

Кроме того, вы просили сравнения. VB и JScript создают замыкания практически одинаково.

47
ответ дан 26 November 2019 в 21:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: