当枚举项发生变化时,是否会影响枚举?
想象一下,在
foreach(var item in enumerable)
可枚举项发生变化时。 会影响当前的foreach吗?
示例:
var enumerable = new List<int>();
enumerable.Add(1);
Parallel.ForEach<int>(enumerable, item =>
{
enumerable.Add(item + 1);
});
它会永远循环吗?
Imagine that during a
foreach(var item in enumerable)
The enumerable items change. It will affect the current foreach?
Example:
var enumerable = new List<int>();
enumerable.Add(1);
Parallel.ForEach<int>(enumerable, item =>
{
enumerable.Add(item + 1);
});
It will loop forever?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
一般来说,它应该抛出异常。
GetEnumerator() 的
List
实现 提供一个Enumerator
对象,其MoveNext()
方法如下所示(来自 Reflector) :list._version
在每次修改 List 的操作中都会被修改(递增)。Generally, it should throw an exception.
The
List<T>
implementation of GetEnumerator() Provides anEnumerator<T>
object whoseMoveNext()
method looks like this (from Reflector):The
list._version
is modified (incremented) on each operation which modifies the List.取决于枚举器的性质。 当集合更改时,其中许多会抛出异常。
例如,如果集合在枚举期间发生更改,
List
会抛出InvalidOperationException
。Depends on the nature of the enumerator. Many of them throw exception when the collection changes.
For instance,
List<T>
throws anInvalidOperationException
if the collection changes during enumeration.Microsoft 的
IEnumerable
文档[和IEnumerable
——非通用名称将同时引用两者]建议,每当实现这些接口的对象发生更改时,它都应该失效它之前生成的任何IEnumerator
[IEnumerator
] 实例,导致它们在将来的访问尝试中抛出InvalidOperationException
。 尽管 Microsoft 的文档中没有记录这种立场的任何变化,但他们的 IEnumerable 的实际实现似乎遵循一个更宽松的规则,即如果底层集合被修改; 如果它不能“明智地”运行,它应该抛出InvalidOperationException
。 不幸的是,由于该规则没有明确说明,而是从其类的行为中推断出来,因此尚不清楚“合理”行为到底意味着什么。我所知道的所有 Microsoft 类如果不能满足以下条件,在更改集合时都会抛出异常:
如果有一些方法可以让集合报告它们是否可以满足上述标准(即使在修改时也不会抛出异常),那将会很有帮助,因为当尝试删除满足特定标准的所有项目时,它们可能非常有用。
Microsoft's documentation for
IEnumerable
[andIEnumerable<T>
--non-generic names will refer to both] recommends that any time an object implementing those interfaces is changed, it should invalidate any instances ofIEnumerator
[IEnumerator<T>
] which it has previously produced, causing them to throwInvalidOperationException
on future access attempts. Although nothing in Microsoft's documentation has documented any change from this stance, their actual implementations ofIEnumerable
seem to follow a looser rule, which is that anIEnumerator
should not behave nonsensically if the underlying collection is modified; it should throwInvalidOperationException
if it can't behave "sensibly". Unfortunately, since that rule is not explicitly stated but rather inferred from the behavior of their classes, it's not clear what exactly "sensible" behavior should mean.All of the Microsoft classes that I know of will will throw an exception when a collection is changed if they cannot meet the following criteria:
It would be helpful if there were some means via which collections could report whether they can satisfy the above criteria (without throwing exceptions) even when modified, since they can be very useful when trying to e.g. remove all items which meet a certain criterion.
这完全取决于 IEnumerable 的实现方式。
对于 List,它将抛出 IllegalOperationException。 但不要依赖 IEnumarable 的这种行为。 有些循环会无限循环,并且会很快抛出 OutOfMemory 异常。
This fully depends on how IEnumerable is implemented.
With a List, It will throw an IllegalOperationException. But don't rely on this behaviour for IEnumarables. Some loop endless and will throw an OutOfMemoryexception quickly.