C# 封闭工程?

C# 封闭工程?,c#,closures,C#,Closures,可能重复: 今天我遇到了一个关于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 }; Li

可能重复:

今天我遇到了一个关于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();
    }
}
}
当我在控制台应用程序中运行它时,屏幕上打印了五个5。为什么?我就是不明白。我问过一些人,他们只是说这段代码中有闭包,但我不是很清楚,我记得在javascript中,我经常遇到闭包,但在上面的代码中,为什么会有闭包?thx.

在C4中,foreach循环的所有迭代都共享相同的变量,因此具有相同的闭包

说明书上说:

然后扩展到:

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

      embedded-statement 
    } 
  } 
  finally
  {  
    … // Dispose e 
  } 
}
您可以看到,v是在while循环之外的一个块中声明的,这导致了这种共享行为

这可能会在C5中发生变化

我们正在找零钱。在C5中,foreach的循环变量在逻辑上位于循环内部,因此每次闭包都会在变量的新副本上关闭。for循环将不会更改

在C4中,foreach循环的所有迭代都共享同一个变量,因此具有相同的闭包

说明书上说:

然后扩展到:

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

      embedded-statement 
    } 
  } 
  finally
  {  
    … // Dispose e 
  } 
}
您可以看到,v是在while循环之外的一个块中声明的,这导致了这种共享行为

这可能会在C5中发生变化

我们正在找零钱。在C5中,foreach的循环变量在逻辑上位于循环内部,因此每次闭包都会在变量的新副本上关闭。for循环将不会更改


关键是,在foreach循环中创建委托时,是在循环变量x上创建闭包,而不是在其当前值上创建闭包


只有在操作中执行委托时,才会确定该值,即当时的x值。由于您已经完成了foreach循环,因此该值将是数据数组中的最后一项,即5。

关键在于,当您在foreach循环中创建委托时,您是在循环变量x上创建闭包,而不是在其当前值上创建闭包


只有在操作中执行委托时,才会确定该值,即当时的x值。由于您已经完成了foreach循环,因此该值将是数据数组中的最后一项,即5。

看看:这个问题几乎每天都会被问到。请参阅,了解有关该问题的详细讨论。看一看:这个问题几乎每天都有人问。关于这个问题的详细讨论,请参阅。+1:非常清楚和简洁的解释。需要注意的是,最后一句话只适用于C4和更早的版本……正如你已经指出的,因此我不想重复它-+1:解释得很清楚,很简洁。需要注意的是,最后一句话只适用于C4和更早的版本……正如你已经指出的,所以我不想重复-为什么早期规范说v在while循环内声明为什么早期规范说v在while循环内声明