循环浏览操作列表

本文关键字:列表 操作 浏览 循环 | 更新日期: 2023-09-27 18:26:50

我不明白如何循环遍历Action列表。当我尝试它时,我最终得到的值与上一次迭代相同。

以下是代码(简化示例):

string[] strings = { "abc", "def", "ghi" };
var actions = new List<Action>();
foreach (string str in strings)
    actions.Add(new Action(() => { Trace.WriteLine(str); }));
foreach (var action in actions)
    action();

输出:

ghi
ghi
ghi

为什么它在执行操作时总是选择strings中的最后一个元素
我如何才能达到预期的输出,即:

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); }));
}

此行为由闭包决定。

lambda中存在的变量是引用,而不是值副本。这意味着它指向str假设的最新值,在您的情况下是"ghi"。这就是为什么每次调用都会转到相同的内存位置,并自然恢复相同的值。

如果您编写代码,就像提供的答案一样,您将强制C#编译器每次重新生成一个新的值,因此一个新的地址将被传递给labmda,因此每个lambda都将具有其自己的

顺便说一句,如果我没有错的话,C#团队承诺修复C# 5.0中的这种非自然行为。因此,最好查看他们关于这个主题的博客,以了解未来的更新。

这是一个非常复杂的情况。简单的答案是在将局部变量分配给闭包之前创建一个副本:

string copy = str;
actions.Add(new Action(() => { Trace.WriteLine(copy); }));

查看这篇关于闭包的文章,了解更多信息。