C#Closure有效吗?

Cha*_*Shi 1 c# closures

可能重复:
C#在foreach中重用变量是否有原因?
循环操作列表

今天我遇到了关于C#foreach函数的问题,它并没有像我预期的那样给我正确的结果.这是代码:

using System;
using System.Collections.Generic;

namespace ConsoleApplication1
{
class Program
{
    static void Main(string[] args)
    {
        int[] data = new int[] { 1, 2, 3, 4, 5 };
        List<Func<int>> actions = new List<Func<int>>();
        foreach (int x in data)
        {
            actions.Add(delegate() { return x; });
        }
        foreach (var foo in actions)
        {
            Console.WriteLine(foo());   
        }
        Console.ReadKey();
    }
}
}
Run Code Online (Sandbox Code Playgroud)

当我在控制台应用程序中运行它并且它在屏幕上打印了5个5.为什么?我只是无法理解.曾经问过一些人,他们只是说这个代码中有封闭,但我对此并不十分清楚,我记得在javascript中,我经常遇到封闭,但在上面的代码中,为什么会有封闭?谢谢.

Cod*_*aos 6

在C#4中,foreach循环的所有迭代共享相同的变量,因此具有相同的闭包.

规范说:

foreach (V v in x) embedded-statement 
Run Code Online (Sandbox Code Playgroud)

然后扩展到:

{  
  E e = ((C)(x)).GetEnumerator(); 
  try
  { 
    V v; 
    while (e.MoveNext())
    { 
      v = (V)(T)e.Current; 

      embedded-statement 
    } 
  } 
  finally
  {  
    … // Dispose e 
  } 
}
Run Code Online (Sandbox Code Playgroud)

您可以看到它vwhile-loop 外部的块中声明,这会导致此共享行为.

这可能会在C#5中改变.

我们正在进行重大改变.在C#5中,foreach的循环变量将在逻辑上位于循环内部,因此闭包每次都会关闭变量的新副本."for"循环不会改变.

http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx