C#对象引用和Action类型

Mar*_*k W 5 c# lambda reference

我有一个关于ActionC#中类型和Lambdas 的快速问题.这是代码:

    static void Main(string[] args)
    {
        List<Action> actions = new List<Action>();

        for (int I = 0; I < 10; I++)
            actions.Add(new Action(() => Print(I.ToString())));

        foreach (Action a in actions)
        {
            a.Invoke();
        }
        actions.Clear();

        int X;
        for (X = 0; X < 10; X++)
        {
            int V = X;
            actions.Add(new Action(() => Print(V.ToString())));
        }

        foreach (Action a in actions)
        {
            a.Invoke();
        }
        Console.ReadLine();
    }


    public static void Print(string s)
    {
        Console.WriteLine(s);
    }
Run Code Online (Sandbox Code Playgroud)

如果运行此代码,您将看到它连续十次输出10次,然后第二次输出数字0-9.它显然与我使用X vs I的方式有关,以及我如何在第二个循环中每次给我的动作一个新变量V ...可能每个新V都是内存中的新地址,但我是努力理解为什么I.ToString()在第一个循环中没有做同样的事情...为什么第一个Action中使用的I.ToString()与第二个例子的工作方式不一样?

Sea*_*ean 5

for循环有效扩大了这个编译器:

{
  int I;
  for (I = 0; I < 10; I++)
  {
    actions.Add(new Action(() => Print(I.ToString())));
  }
}
Run Code Online (Sandbox Code Playgroud)

这意味着所有lambda实例捕获相同的实例I,当循环退出时将为10.

在第二个示例中,将值复制到范围为for语句正文的变量中,并且lambda捕获此本地.每次重复循环都会有一个唯一的局部.

重要的是要意识到你没有捕获变量的值,而是捕获变量本身.这就是为什么第一个例子不起作用,但第二个例子不起作用.