3

testit() 方法是一个闭包。aString 已超出范围,但 testit() 仍然可以在其上执行。testit2() 使用的变量没有超出范围(mystring),但也没有传递给 testit2()。testit2() 是否被视为闭包?

string mystring = "hello world";
Action testit = new Action(delegate { string aString = "in anon method"; Debug.WriteLine(aString); });
testit();

//capture mystring.  Is this still a closure?
Action testit2 = new Action(delegate { Debug.WriteLine(mystring); });
//mystring is still in scope
testit2();

在第二个示例中,可以在方法之外更新 mystring,这些更改将反映在 testit2() 中。这不像普通方法,它只能将 mystring 作为参数捕获。

4

3 回答 3

6

这两个示例都是匿名函数。第二个使用闭包来捕获局部变量。变量相对于匿名函数的作用域生命周期不影响是否创建闭包来使用它。只要变量在匿名函数外部定义并在内部使用,就会创建一个闭包。

第一个匿名函数不使用本地状态,因此不需要闭包。它应该编译成静态方法。

这是必要的,因为匿名函数可以超过当前函数的生命周期。因此,必须捕获匿名函数中使用的所有本地变量,以便以后执行委托。

于 2009-02-16T19:48:56.360 回答
3

闭包不会捕获范围内的,而是捕获范围的实际定义。因此,任何其他引用同一范围的代码都可以修改其中的变量。

于 2009-02-16T19:50:02.193 回答
1

testit并不是testit2真正的闭包——它只使用本地定义的变量,而不是“父”环境中的变量(例如mystring)。

但是,我认为两者都是闭包,因为它们有能力从其封闭环境中捕获变量,这要归功于匿名方法。

于 2009-02-16T19:50:59.320 回答