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

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

问题描述

我遇到了一个关于C#的有趣问题。我有如下代码。

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#编译器创建了一个new变量每次触及变量声明。事实上,它将创建适当的新的闭包对象,如果你引用多个范围中的变量,它变得复杂(在实现方面),但它工作原理:)

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 :)

请注意,这个问题更常见的情况是使用 for 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天全站免登陆