Why use ImmutableList over ReadOnlyCollection?

C#.NetImmutable Collections

C# Problem Overview


.NET 4.5 has a new namespace System.Collections.Immutable

> This package provides collections that are thread safe and guaranteed to never change their contents, also known as immutable collections.

I'm confused. Isn't the thread safety problem already solved by the ReadOnlyCollection class? Why use ImmutableList instead?


I know there's also an IReadOnlyList interface. That doesn't solve the thread safety problem implicitly, because other threads may edit the object by another interface.

C# Solutions


Solution 1 - C#

With a ReadOnlyCollection:

> 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.

This can't happen with an ImmutableList.

Solution 2 - C#

ReadOnlyCollection<T> doesn't solve any of the thread safety problems. It is merely a wrapper around Ilist<T>. It doesn't exposes members to modify the collection, but you can always modify it with the underlying collection reference.

If the underlying collection is modified, it isn't safe to enumerate the ReadOnlyCollection<T>. If you do, you'll get the same InvalidOperationException with message "Collection was modified; enumeration operation may not execute...".

From ReadOnlyCollection<T>

> A ReadOnlyCollection can support multiple readers concurrently, as > long as the collection is not modified. Even so, enumerating through a > collection is intrinsically not a thread-safe procedure. To guarantee > thread safety during enumeration, you can lock the collection during > the entire enumeration. To allow the collection to be accessed by > multiple threads for reading and writing, you must implement your own > synchronization.

ImmutableList on the other hand is immutable and thus inherently thread safe.

Solution 3 - C#

ReadOnlyCollection, as the name suggests, can only be read.

On the other hand, you can append/remove items to/from an ImmutableList by calling its Add/Remove/Clear methods, for example, which return a new immutable list.

Solution 4 - C#

In multi-threaded scenarios, be advised that read-only collections are still not thread-safe.

From the ReadOnlyCollection<T> documentation: > ... if changes are made to the underlying collection, the read-only collection reflects those changes

Since collections, like List<T> and others, are not thread safe, so is not the read-only collection.

Important: There are some corner cases which you won't find explicitly explained in MSDN. Some of the operations that seemingly only read content of a collection, are in fact modifying the internal structures of the collection. Why is this not specified? - One obvious reason is because that is an implementation detail which doesn't reflect on the API. The result is that even if you don't modify the List<T> wrapped into an ReadOnlyCollection<T>, and only use getters, the crash could still happen in multi-threaded environment!

Bottom line is that common collections, even when wrapped into a ReadOnlyCollection cannot be used in multi-threaded environment out of the box.

As opposed to ReadOnlyCollection, immutable collections do guarantee that none of the internal structures will ever change after a reference to a collection has been obtained. Note that these structures are still not truly immutable. They are, instead, freezable. That means that the structure will internally change for a while until it is frozen and returned to the caller. Beyond that point, all other calls on the immutable collection will only make modifications outside the structures accessible through the original reference.

Conclusion: Read-only collections are not thread-safe; immutable collections are thread-safe.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionColonel PanicView Question on Stackoverflow
Solution 1 - C#James ThorpeView Answer on Stackoverflow
Solution 2 - C#Sriram SakthivelView Answer on Stackoverflow
Solution 3 - C#dcastroView Answer on Stackoverflow
Solution 4 - C#Zoran HorvatView Answer on Stackoverflow