为什么以下代码会打印两次11?
在这种情况下,当操作被调用时,变量i会超出作用域吗?因此,这些操作留下了一种类似于悬空指针的引用吗?
int i = 10;
Action fn1 = () => Console.WriteLine(i);
i = 11;
Action fn2 = () => Console.WriteLine(i);
fn1();
fn2();
输出 11 11
根据这篇帖子中的回答 - 如何告诉C# lambda函数捕获一个副本而不是引用? - lambda函数被转换为一个包含被捕获变量副本的类。如果是这样,我的例子不应该打印10和11吗?
现在,当lambda函数通过引用捕获时,它如何影响所捕获变量的生命周期。例如,假设上述代码片段在一个函数中,并且Actions的作用域对于变量是全局的,像这样:
class Test
{
Action _fn1;
Action _fn2;
void setActions()
{
int i = 10;
_fn1 = () => Console.WriteLine(i);
i = 11;
_fn2 = () => Console.WriteLine(i);
}
static void Main()
{
setActions();
_fn1();
_fn2();
}
}
在这种情况下,当操作被调用时,变量i会超出作用域吗?因此,这些操作留下了一种类似于悬空指针的引用吗?
fn1
修改了i
,那么在fn2
中需要可见。至于如何验证它:使用ildasm而不是ilspy,或者(如果可以的话)在ilspy中禁用“优化”(这样它就可以少做一些工作来重构原始的C#代码)。 - Jon Skeet