在将项目添加到循环集合时Foreach

时间:2009-09-15 08:41:57

标签: c# .net

情况就是这样:

我正在浏览一些代码,我想知道以下语句是否接受所选集合的引用,或者当foreach循环完成时它是否替换原始对象的副本。如果是第一个,是否需要新发现的页面并将它们加入循环中?

foreach(Page page in Pages)
{
    page.AddRange(RetrieveSubPages(page.Id));
}
编辑:对不起,我写了一个错字。

应该是这样的:

foreach(Page page in pages)
{
    pages.AddRange(RetrieveSubPages(page.Id));
}

我想说的是,如果我在枚举集合中添加一些对象,它会在foreach中加入这些对象吗?

7 个答案:

答案 0 :(得分:5)

看起来代码不会修改Pages集合,而是修改Page集合中Pages对象中对象的内容。 Page类型至少具有类似方法的集合。

通常,每个集合以适合自身的方式实现迭代,并且在迭代时通常变得不可修改,但是可以通过拍摄自身的快照来实现迭代的集合。

没有机制来检测循环的退出,这将允许在该点采取行动(考虑这将如何与异常交互,在循环体中断开和返回)。

答案 1 :(得分:4)

在大多数情况下,foreach对生活集合起作用(没有显式克隆),如果您在枚举时尝试更改集合,则枚举器会中断异常。因此,如果您要添加Pages,则会遇到问题。

答案 2 :(得分:2)

我认为最安全的方法是:

Array<Page> newpages = new Array<Page>();    
foreach(Page page in pages)
{
    newpages.AddRange(RetrieveSubPages(page.Id));
}

pages.AddRange(newpages);

如果你想进入子页面,你必须稍微扩展一下。

答案 3 :(得分:1)

foreach使用枚举器。 使用foreach循环的集合必须实现IEnumerable(或IEnumerable<T>)。 然后,foreach调用该集合的GetEnumerator方法,并使用Enumerator遍历集合。

答案 4 :(得分:1)

您没有修改您枚举的集合,因此您对此代码不会有任何问题。

如果正在枚举集合的克隆,那也是无关紧要的,因为集合和克隆两者所包含的对象仍然是相同的(引用等于)。

答案 5 :(得分:1)

在回答您的问题时,它不会复制。

它创建一个枚举器并遍历该集合。如果在发生此枚举时更改集合,在foreach本身或异步中更改集合,则会出现异常:

mscorlib.dll中出现未处理的“System.InvalidOperationException”类型异常

其他信息:收集已修改;枚举操作可能无法执行。

您可以使用临时集合并在之后加入两者,或者不使用枚举器。

    for (int i = 0; i < pages.Count; i++)
    {
        test.AddRange(RetrieveSubPages(pages[i].Id));
    }

答案 6 :(得分:0)

我很确定你会得到一个例外,抱怨基础集合被修改了