Я аргументирую, поскольку int является типом значения, фактическое значение, которое передается в Console.WriteLine(), копируется
Это точно правильно. При вызове WriteLine
значение будет скопировано.
Итак, когда вы звоните WriteLine
? Это не в цикле for
. В этот момент вы ничего не пишете, вы просто создаете делегата.
Только в цикле foreach
, когда вы вызываете делегата, именно в это время значение переменной i
копируется в стек для вызова WriteLine
.
Итак, каково значение i
во время цикла foreach
? Это 10 для каждой итерации цикла foreach
.
Итак, теперь вы спрашиваете: «Ну, как i
что-либо во время foreach loop, isn't it out of scope
. Ну, нет, это не так. Это демонстрирует «закрытие». Когда анонимный метод ссылается на переменную, область действия этой переменной должна длиться столько времени, сколько как этот анонимный метод, который может быть в течение любого периода времени. Если вообще ничего особенного не делается, чтение переменной будет случайным мусором, содержащим все, что случилось, застрявшее в этом месте в памяти. С# активно следит за тем, чтобы ситуация не могла произойти .
Так что же он делает? Он создает класс закрытия; это класс, который будет содержать ряд полей, представляющих все, что закрыто. Другими словами, код будет рефакторинг, чтобы он выглядел примерно так:
public class ClosureClass
{
public int i;
public void DoStuff()
{
Console.WriteLine(i);
}
}
class Program
{
delegate void Writer();
static void Main(string[] args)
{
var writers = new List<Writer>();
ClosureClass closure = new ClosureClass();
for (closure.i = 0; closure.i < 10; closure.i++)
{
writers.Add(closure.DoStuff);
}
foreach (Writer writer in writers)
{
writer();
}
}
}
Теперь у нас обоих есть имя для нашего анонимного метода (всем анонимным методам имя дается компилятором), и мы можем гарантировать, что переменная будет жить до тех пор, пока жив делегат, ссылающийся на анонимную функцию.
Глядя на этот рефакторинг, я надеюсь, понятно, почему в результате 10
печатается 10 раз.
08.03.2013