Collection change security with yield return statements

292 views Asked by At

Using yield return Statements I always wonder wheter to implement a version count:

private IEnumerator<string> GetStrings()
{
    int initialVersion = _version; // Where _version is incremented everytime the list changes
    foreach(string s in _listInternal)
    {
        if (initialVersion != _version)
            throw ...;
        yield return s; 
    }
}

foreach(string s in _listInternal) would catch this in this case of course, but if I do not use a collection or list as source, can there be problems?

If i change the collection that creates the enumerator it normally uses this _version field to protect itself from being changed while an iterator iterates throug the items. This is also a Problem when multiple threads work on it.

2

There are 2 answers

0
Servy On BEST ANSWER

There's no need, assuming _listInternal is in fact a List<T>. The List enumerator already implements this functionality; its enumerator will throw an exception if you mutate the collection while iterating it, and that exception will propagate up through your iterator block.

If your iterator block is based on an underlying collection that doesn't already have this behavior, or there is mutable state besides just some underlying collection that you use, but that cannot change, then you may want to use this pattern, yes.

Of course, in order to be able to implement this pattern you need to have some way of incrementing the version number when the underlying data is changed. Sometimes, if you're using a collection you don't have control over the code for, you just can't do that.

7
aj.toulan On

No, you will never need to use a version for a yield return, they should be considered atomic.