我有以下代码......
namespace ConsoleApplication2
{
public delegate void Task();
class Scheduler
{
private List<Task> tasks = new List<Task>();
public void AddTask(Task myTask)
{
tasks.Add(myTask);
}
public void Start()
{
foreach (var task in tasks)
task();
}
}
class Program
{
static void Main(string[] args)
{
var list = new List<string>() { "A", "B", "C" };
var scheduler = new Scheduler();
foreach (var item in list)
{
scheduler.AddTask(() => { Console.WriteLine(item); });
}
scheduler.Start();
}
}
}
输出是......
C
C
C
但是,如果我将Main方法的foreach部分更改为:
foreach (var item in list)
{
var i = item;
scheduler.AddTask(() => { Console.WriteLine(i); });
}
我得到以下输出:
A
B
C
我的假设是两个程序都应该生成相同的输出。有人可以解释为什么它的表现如此吗?
答案 0 :(得分:1)
在循环的第一个版本中,item的值在调度程序执行Console时发生变化.Writeline() - item是执行三个任务时值为'C'的局部变量。
在第二个版本中,您正在创建对item的引用,然后在任务中使用它,因此它正确显示当时的值。
如果您安装了ReSharper,它会警告您“访问修改后的闭包”:这是他们对原因的解释:
http://confluence.jetbrains.com/display/ReSharper/Access+to+modified+closure