我觉得我对闭包有很好的理解,如何使用它们,以及它们什么时候有用.但我不明白的是他们实际上是如何在幕后的幕后工作的.一些示例代码:
public Action Counter()
{
int count = 0;
Action counter = () =>
{
count++;
};
return counter;
}
Run Code Online (Sandbox Code Playgroud)
通常,如果闭包没有捕获{count},它的生命周期将被限定为Counter()方法,并且在它完成之后它将消除Counter()的其余堆栈分配.什么时候关闭会发生什么?这个Counter()调用的整个堆栈分配是否存在?它会将{count}复制到堆中吗?它是否从未真正在堆栈上分配,但被编译器识别为关闭,因此总是存在于堆上?
对于这个特殊的问题,我主要关注它在C#中是如何工作的,但是不反对与支持闭包的其他语言进行比较.
Eri*_*ert 47
你的第三个猜测是正确的.编译器将生成如下代码:
private class Locals
{
public int count;
public void Anonymous()
{
this.count++;
}
}
public Action Counter()
{
Locals locals = new Locals();
locals.count = 0;
Action counter = new Action(locals.Anonymous);
return counter;
}
Run Code Online (Sandbox Code Playgroud)
合理?
另外,您要求进行比较.VB和JScript都以完全相同的方式创建闭包.
Joe*_*orn 33
所述编译器(而不是在运行时)创建另一个类/类型.您的闭包函数以及您关闭/提升/捕获的任何变量将作为该类的成员在您的代码中重写..Net中的闭包实现为此隐藏类的一个实例.
这意味着你的count变量完全是一个不同类的成员,并且该类的生命周期与任何其他clr对象一样.在它不再生根之前,它不符合垃圾收集的条件.这意味着只要你有一个可调用的方法引用它就不会去任何地方.