在'foreach'循环中修改列表的最佳方法是什么?

Pol*_*olo 68 .net c# enumeration list enumerable

C#/ .NET 4.0中的一个新功能是,您可以在foreach不获取异常的情况下更改您的枚举.请参阅Paul Jackson的博客文章"并发的有趣副作用:在枚举时从集合中删除项目"以获取有关此更改的信息.

执行以下操作的最佳方法是什么?

foreach(var item in Enumerable)
{
    foreach(var item2 in item.Enumerable)
    {
        item.Add(new item2)
    }
}
Run Code Online (Sandbox Code Playgroud)

通常我使用IList一个缓存/缓冲区直到结束foreach,但是有更好的方法吗?

Rik*_*Rik 69

foreach中使用的集合是不可变的.这非常符合设计.

正如它在MSDN上所说:

foreach语句用于迭代集合以获取所需的信息,但不能用于添加或删除源集合中的项目以避免不可预测的副作用.如果需要在源集合中添加或删除项目,请使用for循环.

Poko提供的链接中的帖子表明在新的并发集合中允许这样做.

  • 你的回答并没有真正回答这个问题.他知道基本的foreach循环是不可变的......他想知道将更改应用于可枚举集合的最佳方法. (17认同)
  • 然后答案是:使用常规的for循环,如引用中所示.我知道OP在C#4.0中提到了这种行为的变化,但是我找不到任何关于它的信息.目前,我认为这仍然是一个相关的答案. (13认同)

tva*_*son 15

在这种情况下使用IEnumerable扩展方法制作枚举的副本,并对其进行枚举.这会将每个内部可枚举中的每个元素的副本添加到该枚举中.

foreach(var item in Enumerable)
{
    foreach(var item2 in item.Enumerable.ToList())
    {
        item.Add(item2)
    }
}
Run Code Online (Sandbox Code Playgroud)


eul*_*rfx 8

如上所述,但使用代码示例:

foreach(var item in collection.ToArray())
    collection.Add(new Item...);
Run Code Online (Sandbox Code Playgroud)


Rol*_*kas 7

为了说明Nippysaurus的答案:如果你要将新项目添加到列表中并且想要在同一枚举中处理新添加的项目,那么你可以使用for循环而不是foreach循环,问题解决了:)

var list = new List<YourData>();
... populate the list ...

//foreach (var entryToProcess in list)
for (int i = 0; i < list.Count; i++)
{
    var entryToProcess = list[i];

    var resultOfProcessing = DoStuffToEntry(entryToProcess);

    if (... condition ...)
        list.Add(new YourData(...));
}
Run Code Online (Sandbox Code Playgroud)

对于可运行的示例:

void Main()
{
    var list = new List<int>();
    for (int i = 0; i < 10; i++)
        list.Add(i);

    //foreach (var entry in list)
    for (int i = 0; i < list.Count; i++)
    {
        var entry = list[i];
        if (entry % 2 == 0)
            list.Add(entry + 1);

        Console.Write(entry + ", ");
    }

    Console.Write(list);
}
Run Code Online (Sandbox Code Playgroud)

最后一个例子的输出:

0,1,2,3,4,5,6,7,8,9,1,3,5,7,9,

清单(15项)
0
1
2
3
4
5
6
7
8
9
1
3
5
7
9


Nip*_*rus 5

for()在这种情况下你真的应该使用而不是foreach()

  • 如果您要更改集合的长度,那么您希望根据新长度而不是原始长度来评估 for 循环,否则可能会出现超出范围的异常 (2认同)