C# lambda,当你想的时候没有取局部变量值? [英] C# lambda, local variable value not taken when you think?

查看:15
本文介绍了C# lambda,当你想的时候没有取局部变量值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们有以下代码:

void AFunction()
{

   foreach(AClass i in AClassCollection)
   {
      listOfLambdaFunctions.AddLast(  () =>  {  PrintLine(i.name); }  );
   }
}

void Main()
{
    AFunction();
    foreach( var i in listOfLambdaFunctions)
       i();
}

有人可能认为上面的代码会和下面的一样:

One might think that the above code would out the same as the following:

void Main()
{

    foreach(AClass i in AClassCollection)
       PrintLine(i.name);
}

然而,事实并非如此.相反,它每次都打印 AClassCollection 中最后一项的名称.

However, it doesn't. Instead, it prints the name of the last item in AClassCollection every time.

看起来好像在每个 lambda 函数中都使用了相同的项目.我怀疑从 创建 lambda 时当 lambda 获取其中使用的外部变量的快照之间可能存在一些延迟.本质上,lambda 持有对局部变量 i 的引用,而不是在创建 lambda 时获取 i 值的快照".

It appears as if the same item was being used in each lambda function. I suspect there might be some delay from when the lambda was created to when the lambda took a snapshot of the external variables used in it. Essentially, the lambda is holding a reference to the local variable i, instead of taking a "snapshot" of i's value when the lambda was created.

为了测试这个理论,我尝试了这个代码:

To test this theory, I tried this code:

string astr = "a string";
AFunc fnc = () => { System.Diagnostics.Debug.WriteLine(astr); };
astr = "changed";
fnc();

而且,惊喜,它输出changed

我使用的是 XNA 3.1 以及随附的 C# 版本.

I am using XNA 3.1, and whichever version of C# that comes with it.

我的问题是:

  1. 发生了什么事?
  2. lambda 函数是否以某种方式存储了对变量的引用"或其他内容?
  3. 有什么办法可以解决这个问题吗?

推荐答案

这是一个修改后的闭包

参见:类似的问题,如访问修改后的闭包

要解决此问题,您必须在 for 循环的范围内存储变量的副本:

To work around the issue you have to store a copy of the variable inside the scope of the for loop:

   foreach(AClass i in AClassCollection) 
   { 
      AClass anotherI= i;
      listOfLambdaFunctions.AddLast(  () =>  {  PrintLine(anotherI.name); }  ); 
   } 

这篇关于C# lambda,当你想的时候没有取局部变量值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆