【问题标题】:Is this still a closure?这还是闭包吗?
【发布时间】:2010-10-07 22:46:07
【问题描述】:

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 作为参数。

【问题讨论】:

    标签: c# .net function closures anonymous-methods


    【解决方案1】:

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

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

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

    【讨论】:

    • 它们是匿名方法,而不是 lambda 表达式(无论如何在 C# 术语中)。然而,lambda 表达式和匿名方法都算作匿名函数。
    • 我觉得用 Softie 挑剔术语很糟糕 :)
    • @Jon,欢迎挑剔。另一个学习新东西的机会。我不知道匿名函数是这两种不同场景的通用术语。我已经习惯在任何地方都称它们为 lambda。匿名函数虽然更难输入 ;)
    【解决方案2】:

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

    【讨论】:

    • 这种闭包被称为“词法闭包”——它捕获了词法范围。
    【解决方案3】:

    testit 不像testit2 真正的那样是一个闭包——它只使用一个本地定义的变量,而不是“父”环境中的一个变量(例如@987654324 @)。

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

    【讨论】:

    • 谢谢。我从这里看你的例子:stackoverflow.com/questions/428617/closures-in-net。 counter 的定义就像 testit() 定义 aString 一样。我相信这意味着你给出的例子并不是最有力的闭包案例,这似乎是你对 testit() 所说的。
    • @4thspace:不,再读一遍这个例子。 counter 是在匿名方法之外定义的,更像是 mystring。
    猜你喜欢
    • 2014-10-21
    • 2013-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多