Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
Большинство разработчиков разумно предполагают, что результатом выполнения этого кода будет “1 2 3”Я бы не сказал, что разумно. Скорее неразумно, ибо такое предположение можно сделать лишь при полном непонимании того, как работают замыкания.
Несколько сотен постов на stackoverflow говорят о том, что очень-но многие разработчики считают именно «1 2 3» естественным результатом.
var actions = new List<Action>();
var jj = 0;
foreach(var i in Enumerable.Range(1, 3))
{
actions.Add(() => Console.WriteLine(i, jj));
jj = jj +1;
}
foreach(var action in actions)
{
action(); //даст для новой версии(5): 1 3 2 3 3 3
}
var actions = new List<Action>();
var jjClosure = new jjClosure();
jjClosure.jj = 0;
foreach(var i in Enumerable.Range(1, 3))
{
// внутренний объект замыкания содержит ссылку на внешний объект замыкания
var iClosure = new iClosure() {i = i, jjClosure = jjClosure};
// () => Console.WriteLine(i, jj) теперь перехало в метод Action замыкания iClosure.
// Тело iClosure.Action выглядит так:
// Console.WriteLine(this.i, this.jjClosure.jj);
actions.Add(iClosure.Action);
}
int i;
for( i=0; i<10; i++ )
{
/* Здесь работаем с одной и той же переменной */
}
for( int i=0; i<10; i++ )
{
/* А здесь для каждой итерации генерируется новая переменная */
}
for( int i=0; i<10; i++ )
{
/* А здесь для каждой итерации создается новый экземпляр Closure, что приводит к сохранению нужного значения переменной i */
}
</sorce>
Замыкания на переменных цикла в C# 5