C# lambda,当你想的时候没有取局部变量值? [英] C# lambda, local variable value not taken when you think?
问题描述
假设我们有以下代码:
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.
我的问题是:
- 发生了什么事?
- lambda 函数是否以某种方式存储了对变量的引用"或其他内容?
- 有什么办法可以解决这个问题吗?
推荐答案
这是一个修改后的闭包
参见:类似的问题,如访问修改后的闭包
要解决此问题,您必须在 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屋!