lambda(或闭包)封装了函数指针和变量。这就是为什么在 C# 中,您可以执行以下操作:
int lessThan = 100;
Func<int, bool> lessThanTest = delegate(int i) {
return i < lessThan;
};
我在那里使用了一个匿名委托作为闭包(它的语法比等效的 lambda 更清晰,更接近 C),它将 lessThan (堆栈变量)捕获到闭包中。评估闭包时,将继续引用 lessThan(其堆栈帧可能已被破坏)。如果我改变小于,那么我改变比较:
int lessThan = 100;
Func<int, bool> lessThanTest = delegate(int i) {
return i < lessThan;
};
lessThanTest(99); // returns true
lessThan = 10;
lessThanTest(99); // returns false
在 C 中,这将是非法的:
BOOL (*lessThanTest)(int);
int lessThan = 100;
lessThanTest = &LessThan;
BOOL LessThan(int i) {
return i < lessThan; // compile error - lessThan is not in scope
}
虽然我可以定义一个带有 2 个参数的函数指针:
int lessThan = 100;
BOOL (*lessThanTest)(int, int);
lessThanTest = &LessThan;
lessThanTest(99, lessThan); // returns true
lessThan = 10;
lessThanTest(100, lessThan); // returns false
BOOL LessThan(int i, int lessThan) {
return i < lessThan;
}
但是,现在我在评估它时必须传递 2 个参数。如果我希望将此函数指针传递给 lessThan 不在范围内的另一个函数,我将不得不通过将其传递给链中的每个函数或将其提升为全局函数来手动使其保持活动状态。
尽管大多数支持闭包的主流语言都使用匿名函数,但并没有要求。你可以有没有匿名函数的闭包,也可以有没有闭包的匿名函数。
总结:闭包是函数指针+捕获变量的组合。