[英]Is this an example of a closure in C#?
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();
}
My understanding is that x is not actually declared as a variable eg. 我的理解是x实际上并没有被声明为变量,例如。 var x = 3. Instead, it's passed into the outer function, which returns a function that returns the original value.
var x = 3.相反,它被传递给外部函数,后者返回一个返回原始值的函数。 At the time it is returning this, it creates a closure around x to remember its value.
在它返回时,它会在x周围创建一个闭包来记住它的值。 Then later on, if you alter s, it has no effect.
然后,如果你改变s,它没有任何效果。
Is this right? 这是正确的吗?
(Output is 3 by the way, which I'd expect). (顺便说一下输出是3,我期待)。
Edit: here's a diagram as to why I think it is 编辑:这是我认为的原因图
x=3 is passed into the func, and it returns a function that simply returns x. 将x = 3传递给func,它返回一个只返回x的函数。 But x doesn't exist in the inner function, only its parent, and its parent no longer exists after I make it null.
但是在内部函数中不存在x,只有它的父元素,并且在我使其为空后它的父元素不再存在。 Where is x stored, when the inner function is ran?
当内部函数运行时,x存储在哪里? It must create a closure from the parent.
它必须从父级创建一个闭包。
Further clarification: 进一步澄清:
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);
};
Output is 0, 1, 2, 3, 4 输出为0,1,2,3,4
However with your example: 但是用你的例子:
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();
}
The output is 5 5 5 5 5, which isn't what you want. 输出是5 5 5 5 5,这不是你想要的。 It hasn't captured the value of the variable, it's merely retained a reference to the original s.
它没有捕获变量的值,它只是保留了对原始s的引用。
Closures are created in javascript precisely to avoid this problem. 闭包是在javascript中精确创建的,以避免此问题。
No, that's not a closure on s
, x
is just an argument to the lambda expression which generates a delegate (which could actually be simplified to x => () => x
. 不,这不是
s
上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());
You'll get 3
and 5
as expected. 你会得到
3
和5
的预期。 In neither case does it actually remember x
from the other time, but it does close on x
locally during the duration of the outer lambda. 在两种情况下它实际上记得
x
从其他的时间,但它确实在接近x
本地外拉姆达的持续期间。
Basically, each call to x => () => x
will create a new () => x
delegate which captures the local value of x
(not of the s
passed in). 基本上,每个呼叫到
x => () => x
将创建一个新的() => x
代表其捕获的本地值x
(未的s
传递)。
Even if you use s
and pass it in, and change it, you still get 3
and 5
: 即使你使用
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());
Now, it does capture on the local variable x
within the local function, which is generated at every call. 现在,它确实捕获本地函数中的局部变量
x
,该函数在每次调用时生成。 So the x
won't persist between invocations of the larger lambda, but it will be captured if changed later in the lambda. 所以
x
不会在较大的lambda的调用之间持续存在,但如果稍后在lambda中进行更改,它将被捕获。
For example, let's say instead you had this: 例如,让我们说你有这个:
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);
In this case, the closure on x
within the anonymous method is more obvious. 在这种情况下,匿名方法中
x
的闭包更为明显。 The results of running this will be 30 and 50 because modifications to x
within the anonymous method affect the closure on the x
local to that anonymous method, however, these do not carry over between calls, because it's only capturing the local x
passed into the anonymous method, and not the s
used to call it. 运行它的结果将是30和50,因为在匿名方法中对
x
修改会影响该匿名方法的x
local上的闭包,但是,这些不会在调用之间进行,因为它只捕获传递给它的本地x
匿名方法,而不是用于调用它的s
。
So, to sum up, in your diagram and example: * main passes s
into the larger lambda ( func in your diagram) * func closes on x
at the time it's called to generate the anonymous method () => x
所以,综上所述,你的图和实施例中:· 主通行证
s
到更大的拉姆达(您的图中FUNC)* FUNC上关闭x
在它被称为产生匿名方法的时间() => x
Once the call to the outer lambda is made (func) the closer begins and ends because it's local to that lambda only and doesn't close on anything from main. 一旦调用外部lambda(func),闭合器就开始和结束,因为它只对那个lambda是局部的,并且不会从main接近任何东西。
Does that help? 这有帮助吗?
No, change 没变
Func<int, Func<int>> func =
x => () =>
{
return x;
};
to 至
Func<int, Func<int>> func =
x => () =>
{
return s;
};
and it closes over the s
variable. 它关闭了
s
变量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.