对于int循环的foreach循环——为什么在删除元素时foreach会引发异常?
对于int循环的foreach循环——为什么在删除元素时foreach会引发异常?
这个问题在此处已有答案:
我想知道为什么我不能在使用foreach循环迭代列表时删除元素,例如:
Listadmin 更改状态以发布 2023年5月21日
就Java而言,答案在javadoc文档中(强调是自己加的):
本类的iterator和listIterator方法返回的迭代器是快速失败的:如果在迭代器创建后,以任何方式(除了通过迭代器自己的remove或add方法)对列表进行任何结构修改,则迭代器会抛出ConcurrentModificationException异常。因此,当面对并发修改时,迭代器会快速而干净地失败,而不是在未来某个不确定的时间冒任意的、不确定性行为的风险。
最初这个问题被标签为C#,现在已经删除了。但是……
如果在集合中向前移除元素,那么for/loop并不关心这一点是不正确的。 如果你同时移除元素,那么你将无法正确地索引删除后的下一个元素,因为索引不再与下一个元素匹配。你只有在从最后一个元素到第一个元素的顺序循环时,才能避免使用for/loop时遇到问题。
foreach也存在同样的问题。枚举器维护一个Current
位置来指向元素,如果你移除当前元素,然后再前进到下一个Next
位置,那么Current
索引器不再指向被移除的元素后面的元素,而是指向被移除的元素后两个位置的元素。
例如:
假设有一个字符串集合,其中包含“鸟类”,“动物”和“鱼类”
- 在foreach开始时,内部的Current值为0(指向“鸟类”)
- 你删除“鸟类”后,“动物”位于索引0(当前Current仍指向此处)
- 你前进到下一个元素(Current = 1,指向“鱼类”)
- 没有异常,Next前进将退出循环。
foreach没有被设计成允许这种情况。