为什么下面的代码会打印 11 两次?
int i = 10;
Action fn1 = () => Console.WriteLine(i);
i = 11;
Action fn2 = () => Console.WriteLine(i);
fn1();
fn2();
输出
11
11
根据这篇文章的答案 -如何告诉 lambda 函数捕获副本而不是 C# 中的引用? https://stackoverflow.com/questions/451779/how-to-tell-a-lambda-function-to-capture-a-copy-instead-of-a-reference-in-c- lambda 被转换为带有捕获变量副本的类。如果是这种情况,我的示例不应该打印 10 和 11 吗?
现在,当 lambda 通过引用捕获时,它如何影响捕获的变量的生命周期。例如,假设上面的代码位于函数中,并且操作的作用域对于变量来说是全局的,如下所示:
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 不会超出范围吗?那么,这些操作是否留下了悬空指针的引用?
如果是这种情况,我的示例不应该打印 10 和 11 吗?
不,因为你只有一个变量 -fn1
捕捉到variable,不是当前的value。所以像这样的方法:
static void Foo()
{
int i = 10;
Action fn1 = () => Console.WriteLine(i);
i = 11;
Action fn2 = () => Console.WriteLine(i);
fn1();
fn2();
}
翻译如下:
class Test
{
class MainVariableHolder
{
public int i;
public void fn1() => Console.WriteLine(i);
public void fn2() => Console.WriteLine(i);
}
void Foo()
{
var holder = new MainVariableHolder();
holder.i = 10;
Action fn1 = holder.fn1;
holder.i = 11;
Action fn2 = holder.fn2;
fn1();
fn2();
}
}
这也回答了您的第二点:变量被“提升”到一个类中,因此只要委托还活着,它的生命周期就会有效地延长。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)