有人能用通俗易懂的语言解释一下闭包是什么吗?

11

可能是重复问题:
什么是.NET中的“闭包”?

我目前正在学习Lambda表达式,但经常听到“闭包”这个词。能否用非常简单的语言向我解释一下它的含义?


20
如果你有一个聪明的五岁孩子,那么“闭包是一个具有自由变量且这些变量在词法环境中绑定的一等公民函数。” - Dominic Rodger
13
你不需要这样做?让你的孩子和其他孩子一起玩吧……(注:标题愚蠢,回答也是愚蠢的……) - Lasse V. Karlsen
4
如果你的智力水平相当于5岁孩子的话,你很可能无法理解闭包。 - JesperE
2
如果你的智力水平只有五岁孩童的程度,那么很可能你也无法理解这些答案。 - Dominic Rodger
一个类似的问题,但是它涉及到“6岁孩子”的部分;请注意完全不同的结果! https://dev59.com/6XVD5IYBdhLWcg3wBm5h - Blaisorblade
2
如果你有一个非常聪明的5岁孩子,那么“如果你继续问那些问题,你永远不会获得性生活”。问题解决了。 - Jorge Córdoba
9个回答

20

我认为这是一个重复的问题: .NET中的‘闭包’是什么?

实质上,闭包是一段可以在以后执行的代码块,但它保留了它最初创建时所处的环境 - 也就是说,即使方法已经执行完毕,它仍然可以使用该方法的局部变量等。


11
这应该是一条评论才对。这是一个获取声望的好方式。:P - Noldorin
1
那么对于 r jorge 来说,适当的做法是什么? - René Nyffenegger
1
哪个五岁的孩子能理解这些内容呢? - Alan

12
您的鞋子在走廊里,夹克在厨房里。出门时请穿上它们和手套(它们在抽屉里)。

现在您可以拿着您的汽车去玩了。11点时,您必须去角落店买面包。

孩子玩耍,忘记世界。

闹钟响了,孩子看到:11点钟!哦-使用“去外面”的方法出门去买面包。


1
大多数孩子在5岁后才学会看时间。他们只是在5岁时忙于学习数字1-10。只是说一下。;-) - Dominic Rodger
他们会听蜂鸣器的声音。但这是关于“编程”孩子的事情,他们在5岁时就开始学习基本数学(尽管他们自己还不能穿上鞋子……) - xtofl
1
我的同事们实际上一直在清理他们的闭包缓存... :( - xtofl
那么孩子在晚上11点到达商店,发现商店已经关门,不再营业了?我以为我们要去那里呢... - Simon_Weaver

11

我喜欢这个Google Javascript示例(你可以轻松将它改成C#)。虽然它不是五岁的孩子能理解的东西,但我觉得就算是普通的五岁孩子也不知道函数是什么。

/*
* When a function is defined in another function and it
*    has access to the outer function's context even after
*    the outer function returns
* An important concept to learn in Javascript
*/

function outerFunction(someNum) {
  var someString = 'Hai!';
  var content = document.getElementById('content');
  function innerFunction() {
    content.innerHTML = someNum + ': ' + someString;
    content = null; // IE memory leak for DOM reference
  }
  innerFunction();
}

3
outerFunction 返回后,innerFunction 将不再可用;尽管如此,这里展示的内容并不需要使用闭包,在 Pascal 和 Java 中也可以实现! - Blaisorblade

8
下面的答案是针对原始问题的,类似于“如何向5岁的孩子解释闭包。”
拿这个乐高积木盒子;建造一个漂亮的小太空船。当你去Billy的房子并带上你的太空船时,使用闭包,即使盒子留在你的卧室中,你仍然可以使用盒子里的所有积木块。

谢谢! :) 但是我不明白如何“使用你乐高积木盒子里的所有部件,即使该盒子留在你的卧室里。”这个盒子不在Billy的房子里,而且我也不能立即从Billy的房子回家。 - StepUp
一个语言如何实现闭包超出了问题的范围。重要的不是如何实现,而是你可以用闭包做什么。 - Alan

5
如果您需要保持简单,那么一个闭包就是带有其上下文的函数。闭包中的函数可以访问在其定义时可以访问的相同变量,无论您从何处调用它。(在Lua中,这些称为upvalues,我认为这是一个非常描述性的术语。) 我第一次在Lua中遇到这个概念,这个定义帮助我理解了这个概念。也许看看Lua会有所帮助:它的简洁和强大是迷人的,并且肯定有助于对其他语言形成某种观点。它的闭包概念将是一个很好的例子。

4
如果这个5岁的孩子懂C#,我会用以下代码示例来解释:
int i = 0;
string result = null;
Action iExaminer = () =>
{
  result = i % 2 == 1 ? "Odd" : "Even";
};
i = 1;
iExaminer();
Console.WriteLine(result);

如果一个5岁的孩子正在学习 LINQ,我会用以下这段代码来解释:

string name = null;
IEnumerable<Customer> query = Customers.Where(c => c.Name == name);
name = "Bob";
 // query is resolved when enumerated (which is now)
 // Where will now call our anonymous method.
foreach(var customer in query)
{
  Console.WriteLine(customer.Name);
}

3
Linq现在是英国学校核心基础阶段的必修要求。 - Dominic Rodger
@DominicRodger 真的吗?你能提供一些证据吗? - lifebalance
3
@lifebalance - 已经过去五年了,但我认为当时是在开玩笑。 - Dominic Rodger

2

计算机科学中的闭包说:

在计算机科学中,闭包是一个具有自由变量的一等函数,这些变量在词法环境中被绑定。

翻译:
闭包将函数周围的变量封装起来,以便该函数可以被传送到其他地方并仍然使用这些变量,例如,假设您被传送到一个远程位置,但仍然可以访问桌子上的咖啡杯。

示例:

function makefunc(x)
{
    return function(){return x}
}

现在使用makefunc,您可以创建许多匿名函数,它们将返回您传递给makefunc的内容。因此,如果您想要一个返回10的函数,请使用makefunc(10)(),虽然这是一个相当无用的方式来获得10 :)

如果makefunc读取x=42,它会重新创建当前环境吗? - René Nyffenegger
@René Nyffenegger,我不太理解,但是使用不同的x值将返回绑定到不同x的不同匿名函数。 - Anurag Uniyal

0

这是一个在C#中实现的简单方法,涉及到闭包的概念。


0

当你知道如何做某件事情时,你可以指定一些(或全部)细节并得到一个闭包

例如,你知道如何买冰淇淋。你知道如果你在任何商店前面该怎么做。但是,如果你想去特定的商店(例如,由于星期天的折扣),你会带着目的去那里买冰淇淋。"在街角的商店买一些冰淇淋"是"买一些冰淇淋"的闭包。实际上,所有这些都是"在某个地方买一些冰淇淋"的闭包:

  • 在街角买一些冰淇淋
  • 买两个冰淇淋
  • 在街角买两个冰淇淋

现在去和你的朋友玩吧,孩子!(我记住不要在孩子面前说这样的话)


还是我把它和投影混淆了吗? - P Shved

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接