在 C# 5.0 中捕获的闭包(循环变量) [英] Captured Closure (Loop Variable) in C# 5.0

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

问题描述

这在 C# 5.0 中工作正常(如预期):

This works fine (means as expected) in C# 5.0:

var actions = new List<Action>();
foreach (var i in Enumerable.Range(0, 10))
{
    actions.Add(() => Console.WriteLine(i));
}
foreach (var act in actions) act();

打印 0 到 9.但是这个显示 10 次 10 次:

Prints 0 to 9. But this one shows 10 for 10 times:

var actions = new List<Action>();
for (var i = 0; i < 10; i++)
{
    actions.Add(() => Console.WriteLine(i));
}
foreach (var act in actions) act();

问题:这是我们在 5.0 之前的 C# 版本中遇到的问题;所以我们不得不为闭包使用循环本地占位符,现在它已修复 - 在 C# 5.0 中 - 在foreach"循环中.但不是在for"循环中!

Question: This was a problem that we had in C# versions before 5.0; so we had to use a loop-local placeholder for the closure and it's fixed now - in C# 5.0 - in "foreach" loops. But not in "for" loops!

这背后的原因是什么(也没有解决 for 循环的问题)?

What is the reasoning behind this (not fixing the problem for for loops too)?

推荐答案

这背后的原因是什么?

What is the reasoning behind this?

我假设你的意思是为什么 for 循环没有改变它?"

I'm going to assume you mean "why wasn't it changed for for loops as well?"

答案是对于 for 循环,现有的行为是完全合理的.如果将 for 循环分解为:

The answer is that for for loops, the existing behaviour makes perfect sense. If you break a for loop into:

  • 初始化器
  • 条件
  • 迭代器
  • 身体

... 那么循环大致是:

... then the loop is roughly:

{
    initializer;
    while (condition)
    {
        body;
        iterator;
    }
}

(当然,iterator 也在continue; 语句的末尾执行.)

(Except that the iterator is executed at the end of a continue; statement as well, of course.)

初始化部分逻辑上只发生一次,所以只有一个变量实例化"是完全合乎逻辑的.此外,在循环的每次迭代中没有变量的自然初始"值 - 没有什么可以说 for 循环 必须 是声明变量的形式在初始化器中,在条件中测试它并在迭代器中修改它.您希望这样的循环做什么:

The initialization part logically only happens once, so it's entirely logical that there's only one "variable instantiation". Furthermore, there's no natural "initial" value of the variable on each iteration of the loop - there's nothing to say that a for loop has to be of a form declaring a variable in the initializer, testing it in the condition and modifying it in the iterator. What would you expect a loop like this to do:

for (int i = 0, j = 10; i < j; i++)
{
    if (someCondition)
    {
        j++;
    }
    actions.Add(() => Console.WriteLine(i, j));
}

将其与 foreach 循环进行比较,看起来就像您为每次迭代声明一个单独的变量.哎呀,该变量是只读的,因此将它视为一个在迭代之间发生变化的变量会 更奇怪.将 foreach 循环视为在每次迭代时声明一个新的只读变量,其值取自迭代器是完全合理的.

Compare that with a foreach loop which looks like you're declaring a separate variable for every iteration. Heck, the variable is read-only, making it even more odd to think of it being one variable which changes between iterations. It makes perfect sense to think of a foreach loop as declaring a new read-only variable on each iteration with its value taken from the iterator.

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

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