<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/changing-immutable-collections-trcigqjxf" -->

---
title: Changing Immutable Collections | daily.dev
description: A C# developer shares his experience migrating an election site codebase from ImmutableList/ImmutableDictionary to ImmutableArray/FrozenDictionary after...
canonical: https://daily.dev/posts/changing-immutable-collections-trcigqjxf
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Changing Immutable Collections | daily.dev
og:description: A C# developer shares his experience migrating an election site codebase from ImmutableList/ImmutableDictionary to ImmutableArray/FrozenDictionary after...
og:url: https://daily.dev/posts/changing-immutable-collections-trcigqjxf
og:image: https://api.daily.dev/og/posts/trCIGqJxf.png
og:image:alt: Changing Immutable Collections
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Changing Immutable Collections

**[Jon Skeet's coding blog](https://daily.dev/sources/jonskeet)** · 8 min read · 0 upvotes · 0 comments

## Summary

A C# developer shares his experience migrating an election site codebase from ImmutableList/ImmutableDictionary to ImmutableArray/FrozenDictionary after feedback that the latter are more efficient for his usage pattern (build-once collections rather than incrementally-built ones). He walks through the migration steps for both types, the complications introduced by ImmutableArray being a value type (nullability handling via .Value or the `is` pattern-matching trick), and benchmark results showing dramatic improvement in one validation method (5.5ms to 0.826ms) while construction benchmarks improved only slightly. He reflects on remaining aesthetic and ergonomic niggles with the mismatched naming and value-type semantics, and notes a comment-thread tip about using `default` and `IsDefault` to handle null-like ImmutableArray values.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://codeblog.jonskeet.uk/2025/12/31/changing-immutable-collections>

## Questions this post answers

### Should I use ImmutableArray or ImmutableList in C# when I build a collection once and never modify it again?

ImmutableArray is designed for that pattern and performs better than ImmutableList when a collection is constructed once (often via LINQ) and never modified afterward, rather than built incrementally with Add calls. In one benchmark, a validation method using read-heavy access improved from 5.5ms to 0.826ms after migrating from ImmutableList/ImmutableDictionary to ImmutableArray/FrozenDictionary.

_daily.dev surfaces real-world benchmarks like this for developers choosing between C# immutable collection types._

### How do I handle null checks for ImmutableArray in C# since it's a value type?

Because ImmutableArray is a value type, nullable parameters become ImmutableArray<T>?, which requires either unwrapping with the .Value property or using the `is` operator to create a new non-nullable local variable, unlike reference-type ImmutableList which supports simple null checks. A third option is passing `default` instead of null and checking the IsDefault property, since ImmutableArray is a struct wrapping an internal array that can itself be null.

_developers migrating to value-type immutable collections can track these nullability gotchas on daily.dev._

### What's the migration path from ImmutableDictionary to FrozenDictionary in C#?

The migration is straightforward: add a using for System.Collections.Frozen, rename custom extension methods from an Immutable prefix to Frozen, call ToFrozenDictionary instead of ToImmutableDictionary, and update property and record parameter declarations accordingly. No ImmutableDictionary-specific construction methods needed replacing in this case, making it a low-friction change compared to migrating ImmutableList to ImmutableArray.

_anyone planning a FrozenDictionary migration can find step-by-step experiences like this via daily.dev._

## Similar posts on daily.dev

- [15 Advanced C\# Mistakes You’re Probably Still Making](https://daily.dev/posts/15-advanced-c-mistakes-you-re-probably-still-making-ctxsuyhsf) · ITNEXT · 36 upvotes · 2 comments
- [Experiment: making TypeScript immutable-by-default](https://daily.dev/posts/experiment-making-typescript-immutable-by-default-wsz7yxyng) · Hacker News · 0 upvotes · 0 comments
- [Incremental Source Generators Done Right: The Equality Contract — Daily DevOps & .NET](https://daily.dev/posts/incremental-source-generators-done-right-the-equality-contract-daily-devops-net-ri5ykd1qp) · Daily DevOps & .NET · 5 upvotes · 0 comments

---

Tags: [#performance](https://daily.dev/tags/performance), [#c#](https://daily.dev/tags/c#)

[View this post on daily.dev](https://daily.dev/posts/changing-immutable-collections-trcigqjxf)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Changing Immutable Collections","url":"https://daily.dev/posts/changing-immutable-collections-trcigqjxf","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/changing-immutable-collections-trcigqjxf"},"datePublished":"2026-10-04T13:05:23.866Z","dateModified":"2026-10-04T13:12:33.412Z","description":"A C# developer shares his experience migrating an election site codebase from ImmutableList/ImmutableDictionary to ImmutableArray/FrozenDictionary after...","image":"https://media.daily.dev/image/upload/s--58gMhC4P--/f_auto/v1722860399/public/Placeholder%2012","thumbnailUrl":"https://media.daily.dev/image/upload/s--58gMhC4P--/f_auto/v1722860399/public/Placeholder%2012","isAccessibleForFree":true,"articleSection":"Jon Skeet's coding blog","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Jon Skeet's coding blog","logo":"https://media.daily.dev/image/upload/s--B4KVP-_K--/f_auto,q_auto/v1791119047/logos/jonskeet?_a=BAMAMicg0","url":"https://daily.dev/sources/jonskeet"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/changing-immutable-collections-trcigqjxf","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"performance,c#","timeRequired":"PT8M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Jon Skeet's coding blog","item":"https://daily.dev/sources/jonskeet"},{"@type":"ListItem","position":3,"name":"Changing Immutable Collections"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/changing-immutable-collections-trcigqjxf#faq","mainEntity":[{"@type":"Question","name":"Should I use ImmutableArray or ImmutableList in C# when I build a collection once and never modify it again?","acceptedAnswer":{"@type":"Answer","text":"ImmutableArray is designed for that pattern and performs better than ImmutableList when a collection is constructed once (often via LINQ) and never modified afterward, rather than built incrementally with Add calls. In one benchmark, a validation method using read-heavy access improved from 5.5ms to 0.826ms after migrating from ImmutableList/ImmutableDictionary to ImmutableArray/FrozenDictionary. daily.dev surfaces real-world benchmarks like this for developers choosing between C# immutable collection types."}},{"@type":"Question","name":"How do I handle null checks for ImmutableArray in C# since it's a value type?","acceptedAnswer":{"@type":"Answer","text":"Because ImmutableArray is a value type, nullable parameters become ImmutableArray<T>?, which requires either unwrapping with the .Value property or using the `is` operator to create a new non-nullable local variable, unlike reference-type ImmutableList which supports simple null checks. A third option is passing `default` instead of null and checking the IsDefault property, since ImmutableArray is a struct wrapping an internal array that can itself be null. developers migrating to value-type immutable collections can track these nullability gotchas on daily.dev."}},{"@type":"Question","name":"What's the migration path from ImmutableDictionary to FrozenDictionary in C#?","acceptedAnswer":{"@type":"Answer","text":"The migration is straightforward: add a using for System.Collections.Frozen, rename custom extension methods from an Immutable prefix to Frozen, call ToFrozenDictionary instead of ToImmutableDictionary, and update property and record parameter declarations accordingly. No ImmutableDictionary-specific construction methods needed replacing in this case, making it a low-friction change compared to migrating ImmutableList to ImmutableArray. anyone planning a FrozenDictionary migration can find step-by-step experiences like this via daily.dev."}}]}
```

