是 C# 闭包中的 Lambda 表达式吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9591476/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 08:02:32  来源:igfitidea点击:

Are Lambda expressions in C# closures?

c#lambda

提问by Stefan H

Are lambda expressions (and to a degree, anonymous functions) closures?

lambda 表达式(在某种程度上,匿名函数)是闭包吗?

My understanding of closures are that they are functions that are treated as objects, which seems to be an accurate representation of what anonymous functions and Lambda expressions do.

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

And is it correct to call them closures? I understand that closures came about (or became popular) due to the lisp dialect, but is it also a general programming term?

称它们为闭包是否正确?我知道由于 lisp 方言,闭包出现(或流行),但它也是一个通用的编程术语吗?

Thanks for any clarification that you can provide!

感谢您提供的任何说明!

采纳答案by Reed Copsey

A lambda may be implemented using a closure, but it is not itself necessarily a closure.

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

A closureis "a function together with a referencing environment for the non-local variables of that function.".

一个封闭是“与该函数的非局部变量引用环境中共同发挥作用。”

When you make a lambda expression that uses variables defined outside of the method, then the lambda must be implemented using a closure. For example:

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

int i = 42;

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

In this case, the compiler generated method must have access to the variable (i) defined in a completely different scope. In order for this to work, the method it generates is a "function together with the referencing environment" - basically, it's creating a "closure" to retrieve access to the variable.

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

However, this lambda:

但是,这个 lambda:

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

does not rely on any "referencing environment", since it's a fully contained method. In this case, the compiler generates a normal static method, and there is no closure involved at all.

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

In both cases, the lambda is creating a delegate("function object"), but it's only creating a closure in the first case, as the lambda doesn't necessarily need to "capture" the referencing environment in all cases.

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

回答by usr

Yes. Closures typically capture variables from the outer scope. Lambdas can do that. However if your lambda does not capture anything, it is not a closure.

是的。闭包通常从外部作用域捕获变量。Lambda 可以做到这一点。但是,如果您的 lambda 没有捕获任何内容,则它不是闭包。

回答by jason

It's "closure" not "clojure."

它是“关闭”而不是“clojure”。

That is not what a closure is. A closure is basically a representation of a function together with any non-local variables that the function consumes.

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

In that sense, lambdas are not closures, but they do cause closures to be generated by the compiler if they close over any variables.

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

If you use ILDASM on an assembly that contains a lambda that closes over some variables, you will see in that assembly a compiler generated class that repsresents the function and those variables that were closed over. That isthe closure.

如果您在包含关闭某些变量的 lambda 的程序集中使用 ILDASM,您将在该程序集中看到一个编译器生成的类,该类代表函数和关闭的那些变量。那就是闭包。

When you say

当你说

functions that are treated as objects,

被视为对象的函数,

that's normally just "function object" (in C# we'd say "delegate") and is common in functional programming.

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

回答by Eric Lippert

Reed's answer is correct; I would just add few additional details:

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

  • lambda expressionsand anonymous methodsboth have closure semantics; that is, they "capture" their outer variables and extend the lifetimes of those variables.

  • anonymous functionis the term we use when we mean a lambda expression or an anonymous method. Yes, that is confusing. Sorry. It was the best we could come up with.

  • a function that can be treated as an object is just a delegate. What makes a lambda a closureis that it captures its outer variables.

  • lambda expressions converted to expression trees also have closure semantics, interestingly enough. And implementing that correctly was a pain in the neck, I tell you!

  • "this" is considered an "outer variable" for the purpose of creating a closure even though "this" is not a variable.

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

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

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

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

  • 即使“this”不是变量,“this”也被视为创建闭包的“外部变量”。