在C#中的循环变量抓获 [英] Captured variable in a loop in C#

查看:152
本文介绍了在C#中的循环变量抓获的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇见了关于C#一个有趣的问题。我有code像下面。

I met an interesting issue about C#. I have code like below.

List<Func<int>> actions = new List<Func<int>>();

int variable = 0;
while (variable < 5)
{
    actions.Add(() => variable * 2);
    ++ variable;
}

foreach (var act in actions)
{
    Console.WriteLine(act.Invoke());
}

我期望它输出0,2,4,6,8,但是,它实际上输出5 10秒。

I expect it to output 0, 2, 4, 6, 8. However, it actually outputs five 10s.

这似乎是由于指一个捕获变量的所有操作。其结果是,当它们被调用,它们都具有相同的输出。

It seems that it is due to all actions referring to one captured variable. As a result, when they get invoked, they all have same output.

有没有办法解决这限制工作让每个操作实例有它自己拍摄的变量?

Is there a way to work round this limit to have each action instance have its own captured variable?

推荐答案

是 - 把变量的副本内循环:

Yes - take a copy of the variable inside the loop:

while (variable < 5)
{
    int copy = variable;
    actions.Add(() => copy * 2);
    ++ variable;
}

您可以把它看作如果C#编译器每次它击中变量声明时创建一个新的局部变量。事实上,它会创建适合新的闭包对象,情况就变得复杂(在执行方面)如果你指的是多个变量的作用域,但它的工作原理:)

You can think of it as if the C# compiler creates a "new" local variable every time it hits the variable declaration. In fact it'll create appropriate new closure objects, and it gets complicated (in terms of implementation) if you refer to variables in multiple scopes, but it works :)

请注意,这个问题更为普遍的现象是使用的foreach

Note that a more common occurrence of this problem is using for or foreach:

for (int i=0; i < 10; i++) // Just one variable
foreach (string x in foo) // And again, despite how it reads out loud

查看C#3.0规范第7.14.4.2对于更多细节,并在封我的文章有更多的例子了。

See section 7.14.4.2 of the C# 3.0 spec for more details of this, and my article on closures has more examples too.

这篇关于在C#中的循环变量抓获的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆