C# 循环执行一系列操作
我不明白如何循环执行C# 循环执行一系列操作,c#,action,enumeration,C#,Action,Enumeration,我不明白如何循环执行操作列表。当我尝试它时,我得到的值与上一次迭代相同 下面是代码(简化示例): 为什么它在执行操作时总是选择字符串中的最后一个元素? 我如何才能达到预期的输出,即: abc def ghi 您的操作是一个闭包,因此它访问str本身,而不是str的副本: foreach (string str in strings) { var copy = str; // this will do the job actions.Add(new Action(() =>
操作
列表。当我尝试它时,我得到的值与上一次迭代相同
下面是代码(简化示例):
为什么它在执行操作时总是选择字符串中的最后一个元素?
我如何才能达到预期的输出,即:
abc
def
ghi
您的操作是一个闭包,因此它访问str
本身,而不是str
的副本:
foreach (string str in strings)
{
var copy = str; // this will do the job
actions.Add(new Action(() => { Trace.WriteLine(copy); }));
}
这是一个相当复杂的情况。简单的答案是在将局部变量分配给闭包之前创建其副本:
string copy = str;
actions.Add(new Action(() => { Trace.WriteLine(copy); }));
有关详细信息,请参见。此行为受限制
lambda中存在的变量是参考和非值副本。这意味着它指向由str
假设的最新值,在您的案例中是“ghi”。这就是为什么每次调用都会转到相同的内存位置并恢复相同的值
如果您编写代码,就像在提供的答案中一样,您强制C#
编译器每次重新生成一个new值,这样一个new地址将被传递给labmda,因此每个lambda都有它自己的变量
顺便说一句,如果我没弄错的话,C#
团队承诺在C#5.0
中修复这种非自然行为。因此,最好查看他们关于这个主题的博客,以了解未来的更新。Gah,你赢了。我知道怎么修,但我记不起原因了。关闭!我需要结束+1:)@Joshua就在不久前,当我深入了解时:)。。。我从未意识到,这可能有助于进一步阅读。谢谢。+1很好的解释。值得一提的是,Java是以另一种方式实现的。如果处理Runnable
(通常)以启动线程,则会将变量复制到新上下文中。这也是为什么Java强制您将它们设置为final
。
foreach (string str in strings)
{
var copy = str; // this will do the job
actions.Add(new Action(() => { Trace.WriteLine(copy); }));
}
string copy = str;
actions.Add(new Action(() => { Trace.WriteLine(copy); }));