static void Main(string[] args)
{
var s = 3;
Func<int, Func<int>> func =
x => () =>
{
return x;
};
var result1 = func(s);
func = null;
s = 5;
var result2 = result1();
Console.WriteLine(result2);
Console.ReadKey();
}
Run Code Online (Sandbox Code Playgroud)
我的理解是x实际上并没有被声明为变量,例如.var x = 3.相反,它被传递给外部函数,后者返回一个返回原始值的函数.在它返回时,它会在x周围创建一个闭包来记住它的值.然后,如果你改变s,它没有任何效果.
这是正确的吗?
(顺便说一下输出是3,我期待).
编辑:这是我认为的原因图

将x = 3传递给func,它返回一个只返回x的函数.但是在内部函数中不存在x,只有它的父元素,并且在我使其为空后它的父元素不再存在.当内部函数运行时,x存储在哪里?它必须从父级创建一个闭包.
进一步澄清:
int s = 0;
Func<int, Func<int>> func =
x => () =>
{
return x;
};
for (s = 0; s < 5; s++)
{
var result1 = func(s);
var result2 = result1();
Console.WriteLine(result2);
};
Run Code Online (Sandbox Code Playgroud)
输出为0,1,2,3,4
但是用你的例子:
static void Main(string[] args)
{
int s = 0;
Func<int, Func<int>> func =
x => () =>
{
return s;
};
List<Func<int>> results = new List<Func<int>>();
for (s = 0; s < 5; s++)
{
results.Add(func(s));
};
foreach (var b in results)
{
Console.WriteLine(b());
}
Console.ReadKey();
}
Run Code Online (Sandbox Code Playgroud)
输出是5 5 5 5 5,这不是你想要的.它没有捕获变量的值,它只是保留了对原始s的引用.
闭包是在javascript中精确创建的,以避免此问题.
Jam*_*are 12
不,这不是一个闭包s,x只是lambda表达式的一个参数,它生成一个委托(实际上可以简化为x => () => x.
Func<int, Func<int>> func = x => () => x;
var a = func(3);
var b = func(5);
Console.WriteLine(a());
Console.WriteLine(b());
Run Code Online (Sandbox Code Playgroud)
你会得到3和5预期的一样.在两种情况下它实际上记得x从另一个时间,但它确实收于x外的λ的持续期间本地.
基本上,每次调用x => () => x都会创建一个新的() => x委托,它捕获本地值x(不是s传入的).
即使您使用s,并传递它,并改变它,你仍然可以3和5:
int s = 3;
Func<int, Func<int>> func = x => () => x;
var a = func(s);
s = 5;
var b = func(s);
// 3 and 5 as expected
Console.WriteLine(a());
Console.WriteLine(b());
Run Code Online (Sandbox Code Playgroud)
现在,它确实捕捉局部变量x 中的局部功能,这是在生成的每一个电话.因此x,在较大的lambda的调用之间不会持续存在,但如果稍后在lambda中进行更改,它将被捕获.
例如,让我们说你有这个:
int s = 3;
Func<int, Func<int>> func = x =>
() => {
Func<int> result = () => x;
x = 10 * x;
return result;
};
var a = func(s);
s = 5;
var b = func(s);
Run Code Online (Sandbox Code Playgroud)
在这种情况下,x匿名方法内的闭包更为明显.运行它的结果将是30和50,因为x在匿名方法内的修改会影响x本地对该匿名方法的闭包,但是,这些不会在调用之间进行,因为它只捕获x传递给匿名方法的本地方法,而不是s习惯称之为.
所以,总结一下,你的图,例如:*主要传递s到更大的拉姆达(FUNC你的图中)*FUNC逢x时,它被称为生成匿名方法的时候() => x
一旦调用外部lambda(func),闭合器就开始和结束,因为它只对那个lambda是局部的,并且不会从main接近任何东西.
这有帮助吗?