for循环和带闭包的foreach循环的不同行为 [英] Different behaviors with a for loop and a foreach loop with closures
问题描述
我无法解释遇到的一个问题.基本上,如果在foreach循环中使用lambda语法,则与在for循环中使用lambda语法相比,将得到不同的答案.在下面的代码中,我在"dispatcher"类中注册了一个委托.然后,我稍后将委托中的委托包装在另一个委托中,并返回这些包裹的委托的列表.然后执行它们.执行包装功能列表的预期输出为1,2.但是,当我结合使用lambda和foreach循环时,我看不到.
I can't explain an issue I've run across. Basically I get a different answer if I use lambda syntax in a foreach loop than if I use it in a for loop. In the code below I register a delegate in a "dispatcher" class. I then later wrap the delegate on the way out in another delegate and return a list of these wrapped delegates. I then execute them. The expected output of executing the wrapped function list is 1,2. However I don't see that when I combine a lambda and a foreach loop.
这不是导致此问题的代码,而是我可以重现的最简单的情况.我宁愿不讨论这种情况的用例,对于为什么会得到我不期望的行为,我感到更加好奇.如果我在lambda语法中使用下面的foreach循环,它将失败.如果我使用新的Action()语法和foreach,则可以使用,如果在for循环中使用lambda语法,则可以使用.谁能解释这是怎么回事.这真让我感到难过.
This is not the code that is causing the problem, but the simplest case I could make to reproduce it. I would prefer not to discuss use cases of this, I'm more curious as to why I get behavior I'm not expecting. If I use the foreach loop below with the lambda syntax it fails. If I use the new Action() syntax and a foreach it works, if I use the lambda syntax in a for loop it works. Can anyone explain what is going on here. This has me really stumped.
public class Holder
{
public Holder(int ID, Dispatcher disp)
{
this.ID = ID;
disp.Register(Something);
}
public int ID { get; set; }
private void Something(int test) { Console.WriteLine(ID.ToString()); }
}
public class Dispatcher
{
List<Action<int>> m_Holder = new List<Action<int>>();
public void Register(Action<int> func)
{
m_Holder.Add(func);
}
public List<Action<int>> ReturnWrappedList()
{
List<Action<int>> temp = new List<Action<int>>();
//for (int i = 0; i < m_Holder.Count; i++) //Works - gives 1, 2
//{
// var action = m_Holder[i];
// temp.Add(p => action(p));
//}
foreach (var action in m_Holder)
{
temp.Add(p => action(p)); //Fails - gives 2,2
//temp.Add(new Action<int>(action)); Works - gives 1,2
}
return temp;
}
}
class Program
{
static void Main(string[] args)
{
var disp = new Dispatcher();
var hold1 = new Holder(1, disp);
var hold2 = new Holder(2, disp);
disp.ReturnWrappedList().ForEach(p => p(1));
}
}
推荐答案
这是臭名昭著的结束循环变量"的陷阱.
This is the infamous "closing over the loop variable" gotcha.
- 第二部分)
这篇关于for循环和带闭包的foreach循环的不同行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!