Обычно переменной v2
выделяется некоторое пространство в стеке в начале кодового блока, в котором она найдена. В конце кодового блока (т. Е. В конце итерации) стек возвращается назад (I Описываю логический сценарий, а не оптимизированное реальное поведение). Следовательно, каждый v2
в действительности отличается от v2
от предыдущей итерации, хотя верно то, что он в конечном итоге займет одну и ту же ячейку памяти.
Однако компилятор обнаруживает, что v2
используется анонимной функцией, созданной лямбда-выражением. Компилятор делает hoist переменная v2
. Компилятор создает новый класс с полем Int32 для хранения значения v2
, ему не выделяется место в стеке. Это также делает анонимную функцию методом этого нового типа. (Для простоты я назову этот безымянный класс именем, назовем его «Вещь»).
Теперь в каждой итерации создается новый экземпляр "Thing", и когда v2
назначается его поле Int32, которое фактически назначается не просто точке в памяти стека , Выражение анонимной функции (лямбда) теперь будет возвращать делегата, который имеет ненулевую ссылку на объект экземпляра, эта ссылка будет на текущий экземпляр из «Вещи».
Когда вызывается делегат для анонимной функции, он будет выполняться как метод экземпляра экземпляра Thing. Следовательно, v2
доступно в качестве поля-члена и будет иметь значение, которое оно будет давать во время итерации, когда был создан этот экземпляр «Вещи».