闭包
闭包就是能够读取其他函数内部变量的函数,在本质上,闭包是将函数内部和函数外部连接起来的桥梁。
只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数”。
C#闭包
- 闭包是一个代码块(在C#中,指的是匿名方法或者Lambda表达式,也就是匿名函数),并且这个代码块使用到了代码块以外的变量,于是这个代码块和用到的代码块以外的变量(上下文)被“封闭地包在一起”。
- 当使用此代码块时,该代码块里使用的外部变量的值,是使用该代码块时的值,并不一定是创建该代码块时的值。
- 正常的函数内部的变量是保存在帧栈中(call stack>record Frame)。
- 当形成闭包以后托管堆就形成一个类用来存放该变量
- 一句话概括,闭包是一个包含了上下文环境的匿名函数。
//闭包中内层的函数可以引用包含在它外层函数的变量,即使外层函数的执行已经终止
//该变量提供的值并非变量创建时候的值,而是在父函数范围内的最终值
class Test
{
public event Action action;
//构造函数
public Test()
{
//value如果没有下面的引用,应该在执行完构造函数就被gc掉
int value = 10;
//这里就形成了闭包,因为当构造函数执行后,其中申明的临时变量value的生命周期被改变了
action = () =>
{
Console.WriteLine(value);
}
//该变量提供的值并非变量创建时候的值,而是在父函数范围内的最终值
for (int i = 0; i < 10; i++)
{
action += () =>
{
Console.WriteLine(i);
}
}
}
public void DoSomething()
{
action();
}
}
//执行DoSomething(),外部输出11个10
Lua闭包
什么是闭包
--嵌套函数
function fun9(x)
-- 在函数内部再声明一个函数,会改变外部函数传入参数的生命周期,从而产生了一个闭包
-- 此处x的生命周期就被延长了
return function(y)
print(x + y)
end
end
fun10 = fun9(5) -- 此处传入的5的生命周期被延长了,在fun10中仍需要使用
fun10(2)
-- 输出7
闭包的数据共享
function shareVar(n)
local function func1()
print(n)
end
local function func2()
n = n + 10
print(n)
end
return func1,func2
end
local f1,f2 = shareVar(1024) --创建闭包,f1,f2两个闭包共享同一份upvalue
f1() -- 输出1024
f2() -- 输出1034
f1() -- 输出1034
f2() -- 输出1044
闭包的数据隔离
function counter()
local i = 0
return function() --匿名函数,闭包
i = i + 1
return i
end
end
counter1 = counter()
counter2 = counter()
-- counter1,counter2 是建立在同一个函数,同一个局部变量的不同实例上面的两个不同的闭包
-- 闭包中的upvalue各自独立,调用一次counter()就会产生一个新的闭包
print(counter1()) -- 输出1
print(counter1()) -- 输出2
print(counter2()) -- 输出1