Lambda表达式是否在C#闭包中?

时间:2012-03-06 20:38:48

标签: c# lambda

lambda表达式(以及程度,匿名函数)是否闭包?

我对闭包的理解是它们是被视为对象的函数,这似乎是匿名函数和Lambda表达式所做的准确表示。

将它们称为闭包是否正确?我知道由于lisp方言,闭包会产生(或变得流行),但它是否也是一般的编程术语?

感谢您提供的任何澄清!

4 个答案:

答案 0 :(得分:104)

lambda可以使用闭包来实现,但它本身不一定是闭包。

closure是“与该函数的非局部变量的引用环境一起的函数。”。

当你创建一个使用在方法之外定义的变量的lambda表达式时,必须使用闭包来实现lambda。例如:

int i = 42;

Action lambda = () => { Console.WriteLine(i); }; 

在这种情况下,编译器生成的方法必须能够访问在完全不同的范围内定义的变量(i)。为了使其工作,它生成的方法是“与引用环境一起工作” - 基本上,它创建了一个“闭包”来检索对变量的访问。

然而,这个lambda:

Action lambda2 = () => { Console.WriteLine("Foo"); }

不依赖于任何“引用环境”,因为它是一个完全包含的方法。在这种情况下,编译器会生成一个普通的静态方法,并且根本不涉及任何闭包。

在这两种情况下,lambda都会创建一个delegate(“函数对象”),但它只在第一种情况下创建一个闭包,因为lambda不一定需要“捕获”引用环境在所有情况下。

答案 1 :(得分:69)

里德的回答是正确的;我只想添加一些额外的细节:

  • lambda表达式匿名方法都有闭包语义;也就是说,它们“捕获”它们的外部变量并延长这些变量的生命周期。

  • 匿名函数是我们在使用 lambda表达式或匿名方法时使用的术语。是的,这很令人困惑。抱歉。这是我们能想到的最好的。

  • 可以作为对象处理的函数只是一个委托。使lambda成为闭包的原因在于它捕获了它的外部变量。

  • 转换为表达式树的lambda表达式也有闭包语义,有趣的是。正确地实施这个是一个痛苦的问题,我告诉你!

  • “this”被认为是“外部变量”,用于创建闭包,即使“this”不是变量。

答案 2 :(得分:12)

这是“封闭”而不是“clojure。”

这不是闭包。闭包基本上是函数的表示以及函数消耗的任何非局部变量。

从这个意义上讲,lambdas不是闭包,但如果它们关闭任何变量,它们确实会导致编译器生成闭包。

如果在包含一个关闭某些变量的lambda的程序集上使用ILDASM,您将在该程序集中看到一个编译器生成的类,该类重新表示该函数以及已关闭的那些变量。 关闭。

当你说

  

被视为对象的函数

通常只是“函数对象”(在C#中我们说“委托”)并且在函数式编程中很常见。

答案 3 :(得分:8)

是。闭包通常从外部范围捕获变量。 Lambdas可以做到这一点。但是,如果你的lambda没有捕获任何东西,它就不是一个闭包。