情况就是这样:
我正在浏览一些代码,我想知道以下语句是否接受所选集合的引用,或者当foreach循环完成时它是否替换原始对象的副本。如果是第一个,是否需要新发现的页面并将它们加入循环中?
foreach(Page page in Pages)
{
page.AddRange(RetrieveSubPages(page.Id));
}
编辑:对不起,我写了一个错字。
应该是这样的:
foreach(Page page in pages)
{
pages.AddRange(RetrieveSubPages(page.Id));
}
我想说的是,如果我在枚举集合中添加一些对象,它会在foreach中加入这些对象吗?
答案 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)
我很确定你会得到一个例外,抱怨基础集合被修改了