tags:

views:

201

answers:

3

Hi, I`m using a Dictionary and I want to change it while I Enumerate through it, but it seems this is not allowed. How can I do this?

Thanks

+1  A: 

I answered it here with respect to queue's but the answer is the same. You can't enumerate with foreach and modify the collection at the same time.

Jason Punyon
A: 

You should store the key or object you want to delete and break the loop, and then use remove method to delete the object from dictionary.

Hope this helps

lakhlaniprashant.blogspot.com
+5  A: 

Don't, basically. It's explicitly not supported. From the docs for Dictionary<,>.GetEnumerator():

An enumerator remains valid as long as the collection remains unchanged. If changes are made to the collection, such as adding, modifying, or deleting elements, the enumerator is irrecoverably invalidated and its behavior is undefined.

Typically the best way is to remember the modifications you want to make, and then perform them afterwards. Or you could take a copy of the dictionary to start with and then iterate through that while you modify the original. If you could give us more information about what you're trying to do, that would help.

Having said this, the new ConcurrentDictionary class in .NET 4.0 does permit this - but the results of the iteration aren't guaranteed - you may see the changes while you're iterating, or you may not.

Jon Skeet
Perhaps more accurately is that they couldn't find a good way to throw IllegalOperationException for ConcurrentDictionary. It is going to cause a *lot* of trouble. I certainly wouldn't recommend it.
Hans Passant
@nobugz: I very much doubt that it's because they *couldn't* throw IllegalOperationException. The point of the concurrent collections is that you can do things *concurrently* with them - that includes iterating. Now you usually want to modify the collection in the same thread that's iterating (as that's easy enough to avoid) but in the general case it's much harder.
Jon Skeet
@jon: the why isn't really relevant, the fact that it doesn't throw the exception is. There are a lot of programmers here that take your posts as gospel, I have to urge you to consider the ramifications of your advice. Mutating the dictionary while iterating it, whether by the same thread or another, has Heisenbug written all over it. From looking at the reflected source code, ConcurrentDirectionary does nothing to avoid mishaps. And the MSDN docs are completely silent about it.
Hans Passant
The MSDN docs *aren't* completely silent about it. From http://msdn.microsoft.com/en-us/library/dd287131(VS.100).aspx - "The enumerator returned from the dictionary is safe to use concurrently with reads and writes to the dictionary, however it does not represent a moment-in-time snapshot of the dictionary. The contents exposed through the enumerator may contain modifications made to the dictionary after GetEnumerator was called." Not exactly silent, is it? I would expect developers to use ConcurrentDictionary when they specifically need concurrency - and to use it appropriately.
Jon Skeet
Also note that I didn't just blindly say "Use ConcurrentDictionary, it solves this problem." I specified that it *permits* concurrent iteration and modification, but also explicitly mentioned that you may or may not see the changes. I can't see how that would mislead anyone.
Jon Skeet