Immutability in C# Part 5: Ready-Made Immutability

If you’ll recall last time, we spent a bit of time hand-rolling an implementation of an immutable stack, only for me to confess at the end that this may have been futile.

Why? Well, as of .NET 4.5.1. immutable collections types will be available as part of the framework in the System.Collections.Immutable namespace. More of this in “Immutable collections ready for prime time.”

This is the third stage of an evolution of threading tools that started with the release of .NET 4.

.NET 4 introduced the concept of Tasks and the Task Parallel Library (TPL) to help simplify the parallelisation of CPU/compute-bound operations.

.NET 4.5/ C#5 Introduced the new async and await keywords to help simplify the unblocking of UI from I/O bound operations. These hooked into the Tasks introduced in .NET 4.

Given that we now have the programmatic constructs to manage and control the threads themselves, the next logical step is to supply thread-safe versions of our favourite data structures to ease the work we have to around this. Happily, we’ll find them in the next version of .NET.

Here are the types that will be introduced:

At the time of writing it was deemed that ImmutableArray<T> was not quite ready, although this should arrive in a future release.

So, let’s briefly crack open the ImmutableStack<T> class, and compare it to our implementation in the previous article.

In our implementation, we had a single parameterless constructor that clients could use to instantiate the stack. The BCL implementation of ImmutableStack<T>  does not expose its constructor. Instead we create a mutable stack via static non-generic ImmutableStack class factory:

var is1 = ImmutableStack.Create(0);
var is2 = ImmutableStack.Create(0, 1, 2, 3);
var is3 = ImmutableStack.CreateRange(new List<T>() { 1,2 });

The last one is a little pointless, but it’s useful to note that we can create an immutable stack from any IEnumerable of the same <T>.

Peek(), Pop() and Push() are broadly the same as our implementation, although Pop does have an extra overload that let’s us see the value that we’ve just popped:

int topValue = myImmutableStack.Peek();
var newStack = myImmutableStack.Push(1);

int poppedVal = 0;
var poppedStack = myImmutableStack.Pop();
poppedStack = myImmutableStack.Pop(out poppedVal);

We also have an IsEmpty property, which would have been an improvement to our implementation, plus a static Empty() property that returns an empty stack for us.

As you can see, there are other immutable collection types that Microsoft have provided. It’s fairly easy to pull them into a sample project from the Nuget package source. I’d recommend that you give it a try.

So, this concludes the series on immutable collections. I hope you have found it of some use.

Leave a Reply