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捕获为参数。
答案 0 :(得分:6)
这两个例子都是匿名函数。第二个使用闭包来捕获局部变量。变量相对于匿名函数的范围生命周期不会影响是否创建闭包以使用它。只要变量在匿名函数之外定义并在其中使用,就会创建一个闭包。
第一个匿名函数不使用本地状态,因此不需要闭包。它应该编译成静态方法。
这是必要的,因为匿名函数可以超过当前函数的生命周期。因此,必须捕获匿名函数中使用的所有本地,以便稍后执行该委托。
答案 1 :(得分:3)
闭包不会捕获作用域中的值,而是捕获作用域的实际定义。因此,任何其他引用相同作用域的代码都可以修改其中的变量。
答案 2 :(得分:1)
testit
并不像testit2
那样真正关闭 - 它只使用本地定义的变量,而不是“父”环境中的变量(例如mystring
)。
但是,我认为两者都是闭包,因为他们有能力从封闭环境中捕获变量,这是由于匿名方法。