Tuesday 13 August 2013

Modify While Iterating II

Last month I wrote about the risks of modifying a Collection while iterating it. Today I've come across a couple of things that complement that entry, so I'll post it here.

Recent versions of .Net Framework brought along 2 very important additions in the land of Collections: Read-Only Collections and Concurrent Collections. Pretty fundamental stuff, but admittedly I hadn't made any use of them until very recently. I had some very wrong assumptions as to how these collections behave regarding the modify while iterating thing, so let's take a look:

Read-Only Collections

I guess due to some incomplete, simultaneous reading of several different pieces of information I had the impression that when you create a Read-Only Collection from a normal collection you were taking a snapshot of such collection, that as such would be independent from the original. Nothing further from the true. As clearly stated in the documentation:

A collection that is read-only is simply a collection with a wrapper that prevents modifying the collection; therefore, if changes are made to the underlying collection, the read-only collection reflects those changes. See Collection for a modifiable version of this class.

I think it's quite important to have this pretty clear, as a common scenario is: your class exposes a Read-Only view of one of one internal collection, and while some consumer threads are iterating over that view your class modifies the internal underlying collection. You'll get the classical InvalidOperationException then. I've written some code to confirm it. You can just disassemble the ReadOnlyCollection.GetEnumerator method and will find this:

public IEnumerator GetEnumerator()
{
 return this.list.GetEnumerator();
}

So the normal Enumerator of the internal collection is being used and this enumerator will do the "have you been modified? check" based on the _version field of the internal collection...

Concurrent Collections

Well, for Concurrent Collections it's easy to deduce that if they allow for Adding/Removing/Updating in parallel, iterating at the same time should not be a problem. Somehow I thought to have read something different somewhere, so I did a fast test to verify that you can continue to iterate a collection that has been modified and no InvalidOperationException will happen.

You could also verify it by peeking for instance into the implementation of ConcurrentQueue, and seeing that it lacks any _version field.

No comments:

Post a Comment