Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between a ReadOnlyDictionary and an ImmutableDictionary?

In C#, what is the key difference (in terms of features or use cases) between these two containers? There doesn't appear to be any information comparing these on Google.

System.Collections.ObjectModel.ReadOnlyDictionary System.Collections.Immutable.ImmutableDictionary

I understand that an ImmutableDictionary is thread-safe. Is the same true of a ReadOnlyDictionary?

This is not a duplicate of How to properly use IReadOnlyDictionary?. That question is about how to use IReadOnlyDictionary. This question is about the difference between the two (which, as someone commented on that thread back in 2015, would be a different question - ie. this one)

like image 327
matt_rule Avatar asked Oct 24 '17 12:10

matt_rule


3 Answers

  • A ReadOnlyDictionary can be initialized once via constructor, then you can't add or remove items from it (they throw NotSupportedExceptions). It's useful if you want to ensure that it won't be modified while it's sent across multiple layers of your application.
  • An ImmutableDictionary has methods to modify it like Add or Remove, but they will create a new dictionary and return that, the original one remains unchanged and the copy of the new immutable dictionary is returned.

Note that:

  • You initialize the ReadOnlyDictionary by passing another dictionary instance to the constructor. That explains why a ReadOnlyDictionary is mutable (if the underlying dictionary is modified). It's just a wrapper that is protected from direct changes.
  • You can't use a constructor for ImmutableDictionary: How can I create a new instance of ImmutableDictionary?

That also explains why the ReadOnlyDictionary is not thread-safe (better: it's as thread-safe as the underlying dictionary). The ImmutableDictionary is thread-safe because you can't modify the original instance (neither directly nor indirectly). All methods that "modify" it actually return a new instance.

But if you need a thread-safe dictionary and it's not necessary that it's immutable, use a ConcurrentDictionary instead.

like image 146
Tim Schmelter Avatar answered Nov 10 '22 07:11

Tim Schmelter


A ReadOnlyDictionary<TKey,TValue> is a wrapper around another existing IDictionary<TKey,TValue> implementing object.

Importantly, whilst "you" (the code with access to the ReadOnlyDictionary) cannot make any changes to the dictionary via the wrapper, this does not mean that other code is unable to modify the underlying dictionary.

So unlike what other answers may suggest, you cannot assume that the ReadOnlyDictionary isn't subject to modification - just that "you" aren't allowed to. So for example, you cannot be sure that two attempts to access a particular key will produce the same result.

like image 37
Damien_The_Unbeliever Avatar answered Nov 10 '22 06:11

Damien_The_Unbeliever


In addition to the current answers, I would add that ImmutableDictionary is slower and usually will use more memory.

  • Why slower? Behind the scenes, the ImmutableDictionary isn't a hash table. It uses an AVL tree which is a self-balancing tree, and therefore, its access complexity is O(logn). On the other hand, the other dictionaries use a hash table behind the scenes and the access complexity for them is O(1).
  • Why more memory allocation? Every time the dictionary is being changed it creates a new dictionary because it is immutable.
like image 1
Misha Zaslavsky Avatar answered Nov 10 '22 06:11

Misha Zaslavsky