2017-02-15 7 views
4

я читал с интересной этой статьей под названием C# Closures Explained, в котором говорится:Когда переменная дважды закрывается, где она хранится?

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

Таким образом, по существу закрытая переменная хранится как переменная-член анонимного класса, которая также содержит делегат, представляющий выражение лямбда или другой код, который закрывает переменную.

Если это так, что происходит, когда метод содержит два разных лямбда-выражения, и оба они ссылаются на одну и ту же локальную переменную?

void Test(IList list) 
{ 
    int i = 0; 

    list.Any(a => { Console.WriteLine("Lambda one says: {0}", i++); return true;}) 
     .Any(a => { Console.WriteLine("Lambda two says: {0}", i++); return true;}); 

} 

Я уверен, что знаю поведение здесь. Мой вопрос: где именно находится i?

+1

FWIW, этот код не скомпилирован. 'Any()' является методом расширения с 'IEnumerable ' и ожидает 'Func ' не 'Action'. – Cameron

+0

@Cameron Если у них нет собственного класса 'Console' со своим методом' WriteLine', который возвращает логическое значение. (И также собственный метод расширения 'Any' для' IList', так как метод LINQ 'Any' не принимает' IList'). – Servy

+0

Все локальные переменные хранятся в стеке выполнения. – jdweng

ответ

3

Существует только один класс закрытия для этого метода, а не один для анонимного метода. То, что один класс будет иметь два метода экземпляра и поле. Поле сохранит значение i, и оба метода будут соответствовать вашим двум анонимным методам.

Смежные вопросы