A Use Case of Immutable Collections

How to implement immutable cache.

Changhui Xu
codeburst

--

Caching can greatly improve an application’s performance by reducing the trips to fetch data that changes infrequently. The consistency of cached values is critical at run-time. At development time, we can avoid some human errors by setting caches to be Immutable Collections, so that cached values are not able to be mutated accidentally in code.

This blog post will use the simplest cache IMemoryCache in .NET Core to demonstrate usages of Immutable Collections, which is also native in .NET framework. The sample code is in this GitHub repository.

Update: If you are using .NET 5 and up, then you can refer to my other article entitled IMemoryCache: Immutable Collections and Unit Tests.

Set and Remove Cache

Let’s assume that we have a collection of Parking Lots that are being frequently queried by LotCodes to get LotNames. The list of Parking Lots won’t change often, which makes sense to store the list of data in memory.

In Startup.cs, we need to register the MemoryCache and desired services. Below is an example case that we define a LotNamesCache to retrieve and manage in memory data.

services.AddMemoryCache();services.AddScoped<ILotNamesCache, LotNamesCache>();

The actual implementation of LotNamesCache is shown as below. We store the <LotCode, LotName> key value pairs as an immutable dictionary. A reference of using System.Collections.Immutable; is needed in order to use the ImmutableDictionary type and the ToImmutableDictionary() method.

With the Immutable Dictionary, we are not able to mess up the original copy of key value pairs.

When you manipulate an immutable dictionary a copy of the original dictionary is made, manipulations applied and a new immutable dictionary is returned.

.Net Docs

There are other collection types in the System.Collections.Immutable Namespace, such as ImmutableArray, ImmutableList, ImmutableHashSet, and so on. We should utilize them as much as we can when dealing with immutable objects.

Unit Tests

The code snippet below shows a simple unit test for the LotNamesCache class. The unit test utilizes an InMemoryDatabase to simulate data persisted in some kind of storage.

Please note lines 26–27, even though the cachedLots adds a new key value pair, the original cachedLots doesn’t retain the new key value pair. This effect is exactly what we want, so that the cached values are consistent and can only be modified when the underlying data source has changes.

That’s all for this quick blog post. Hope it helps. Thanks for reading.

--

--

Lead Application Developer. MBA. I write blogs about .NET, Angular, JavaScript/TypeScript, Docker, AWS, DDD, and many others.