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?
Generally, it should throw an exception.
The List<T>
implementation of GetEnumerator() Provides an Enumerator<T>
object whose MoveNext()
method looks like this (from Reflector):
public bool MoveNext()
{
List<T> list = this.list;
if ((this.version == list._version) && (this.index < list._size))
{
this.current = list._items[this.index];
this.index++;
return true;
}
return this.MoveNextRare();
}
private bool MoveNextRare()
{
if (this.version != this.list._version)
{
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
}
this.index = this.list._size + 1;
this.current = default(T);
return false;
}
The list._version
is modified (incremented) on each operation which modifies the List.
Depends on the nature of the enumerator. Many of them throw exception when the collection changes.
For instance, List<T>
throws an InvalidOperationException
if the collection changes during enumeration.
Microsoft's documentation for IEnumerable
[and IEnumerable<T>
--non-generic names will refer to both] recommends that any time an object implementing those interfaces is changed, it should invalidate any instances of IEnumerator
[IEnumerator<T>
] which it has previously produced, causing them to throw InvalidOperationException
on future access attempts. Although nothing in Microsoft's documentation has documented any change from this stance, their actual implementations of IEnumerable
seem to follow a looser rule, which is that an IEnumerator
should not behave nonsensically if the underlying collection is modified; it should throw InvalidOperationException
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With