使用foreach和lambdas时出现意外行为

时间:2013-09-25 16:48:55

标签: c# foreach lambda

我有以下代码......

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

我的假设是两个程序都应该生成相同的输出。有人可以解释为什么它的表现如此吗?

1 个答案:

答案 0 :(得分:1)

在循环的第一个版本中,item的值在调度程序执行Console时发生变化.Writeline() - item是执行三个任务时值为'C'的局部变量。

在第二个版本中,您正在创建对item的引用,然后在任务中使用它,因此它正确显示当时的值。

如果您安装了ReSharper,它会警告您“访问修改后的闭包”:这是他们对原因的解释:

http://confluence.jetbrains.com/display/ReSharper/Access+to+modified+closure