<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/readonly-vs-immutable-vs-frozen-in-c-differences-and-a-lot-of-benchmarks-tlajiwe2q" -->

---
title: Readonly vs Immutable vs Frozen in C#: differences and...
description: A detailed comparison of three similarly named but distinct C#/.NET collection concepts: Readonly wrappers, Immutable collections...
canonical: https://daily.dev/posts/readonly-vs-immutable-vs-frozen-in-c-differences-and-a-lot-of-benchmarks-tlajiwe2q
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Readonly vs Immutable vs Frozen in C#: differences and (a lot of) benchmarks | daily.dev
og:description: A detailed comparison of three similarly named but distinct C#/.NET collection concepts: Readonly wrappers, Immutable collections...
og:url: https://daily.dev/posts/readonly-vs-immutable-vs-frozen-in-c-differences-and-a-lot-of-benchmarks-tlajiwe2q
og:image: https://api.daily.dev/og/posts/tLAJIWe2q.png
og:image:alt: Readonly vs Immutable vs Frozen in C#: differences and (a lot of) benchmarks
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.

# Readonly vs Immutable vs Frozen in C#: differences and (a lot of) benchmarks

**[Code4IT](https://daily.dev/sources/code4it)** · 23 min read · 0 upvotes · 0 comments

## Summary

A detailed comparison of three similarly named but distinct C#/.NET collection concepts: Readonly wrappers, Immutable collections (System.Collections.Immutable), and Frozen collections (introduced in .NET 8). Readonly collections merely prevent mutation through a reference but can still change if the underlying collection is modified; Immutable collections create true snapshots where every mutation returns a new instance, offering thread safety; Frozen collections are precomputed, lookup-optimized structures ideal for build-once, read-many scenarios. Extensive BenchmarkDotNet results (tested on .NET 10 with collections of 10 to 10,000 elements) show Readonly is cheapest to create, Immutable and Frozen cost much more to build (Frozen up to ~146,000x slower to create at 10,000 elements), but FrozenSet/FrozenDictionary deliver the fastest lookups, especially for non-existing keys. Updating a Frozen collection requires a full rebuild, which is extremely costly compared to in-place Dictionary updates or Immutable's SetItem.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://www.code4it.dev/blog/readonly-vs-immutable-vs-frozen>

## Questions this post answers

### Is a FrozenSet faster than a HashSet for Contains lookups in .NET 8?

Yes, FrozenSet is significantly faster for Contains checks than both HashSet and ImmutableHashSet. In benchmarks with 10,000 elements, FrozenSet took about 2.42 ns versus 6.45 ns for HashSet and 13.29 ns for ImmutableHashSet when checking an existing key, and the gap widens further for non-existing keys (0.65 ns versus 5.31 ns and 13.86 ns respectively).

_daily.dev surfaces benchmarked comparisons like this for developers choosing a collection type for hot lookup paths._

### How much slower is it to create an ImmutableList compared to a ReadOnlyCollection in C#?

Creating an ImmutableList from an array of 10,000 elements takes roughly 102,208 nanoseconds versus about 3.4 nanoseconds for wrapping the same list in a ReadOnlyCollection, making ImmutableList creation around 30,000 times slower. This is because ReadOnlyCollection is just a thin wrapper, while ImmutableList copies elements into a new persistent structure.

_developers weighing immutability against raw speed can track findings like this through daily.dev._

### What is the memory and time cost of updating a FrozenDictionary in .NET?

Updating a FrozenDictionary requires rebuilding it entirely from a modified source dictionary, since frozen structures cannot be mutated in place. For a 10,000-element dictionary, this rebuild costs about 605,496 nanoseconds and allocates roughly 1,130,445 bytes, compared to near-zero allocation and about 9.77 nanoseconds for an in-place Dictionary update.

_daily.dev helps developers deciding between dictionary types weigh costs like this rebuild overhead._

## Similar posts on daily.dev

- [Immutability in PHP Beyond readonly](https://daily.dev/posts/immutability-in-php-beyond-readonly-e2zuz4sl6) · W endell Adriel · 13 upvotes · 1 comments
- [Monotonic Collections: a middle ground between immutable and fully mutable](https://daily.dev/posts/monotonic-collections-a-middle-ground-between-immutable-and-fully-mutable-iypvwtkoo) · Neil Madden · 1 upvotes · 0 comments

---

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

[View this post on daily.dev](https://daily.dev/posts/readonly-vs-immutable-vs-frozen-in-c-differences-and-a-lot-of-benchmarks-tlajiwe2q)

```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":"Readonly vs Immutable vs Frozen in C#: differences and (a lot of) benchmarks","url":"https://daily.dev/posts/readonly-vs-immutable-vs-frozen-in-c-differences-and-a-lot-of-benchmarks-tlajiwe2q","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/readonly-vs-immutable-vs-frozen-in-c-differences-and-a-lot-of-benchmarks-tlajiwe2q"},"datePublished":"2026-10-04T13:07:27.021Z","dateModified":"2026-10-04T13:17:48.459Z","description":"A detailed comparison of three similarly named but distinct C#/.NET collection concepts: Readonly wrappers, Immutable collections...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/1b5ea1a5017c8f553c46ab1e0b997c50?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/1b5ea1a5017c8f553c46ab1e0b997c50?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Code4IT","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":"Code4IT","logo":"https://media.daily.dev/image/upload/s--OaaG4G10--/f_auto,q_auto/v1791119049/logos/code4it?_a=BAMAMicg0","url":"https://daily.dev/sources/code4it"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/readonly-vs-immutable-vs-frozen-in-c-differences-and-a-lot-of-benchmarks-tlajiwe2q","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"performance,.net,c#","timeRequired":"PT23M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Code4IT","item":"https://daily.dev/sources/code4it"},{"@type":"ListItem","position":3,"name":"Readonly vs Immutable vs Frozen in C#: differences and (a lot of) benchmarks"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/readonly-vs-immutable-vs-frozen-in-c-differences-and-a-lot-of-benchmarks-tlajiwe2q#faq","mainEntity":[{"@type":"Question","name":"Is a FrozenSet faster than a HashSet for Contains lookups in .NET 8?","acceptedAnswer":{"@type":"Answer","text":"Yes, FrozenSet is significantly faster for Contains checks than both HashSet and ImmutableHashSet. In benchmarks with 10,000 elements, FrozenSet took about 2.42 ns versus 6.45 ns for HashSet and 13.29 ns for ImmutableHashSet when checking an existing key, and the gap widens further for non-existing keys (0.65 ns versus 5.31 ns and 13.86 ns respectively). daily.dev surfaces benchmarked comparisons like this for developers choosing a collection type for hot lookup paths."}},{"@type":"Question","name":"How much slower is it to create an ImmutableList compared to a ReadOnlyCollection in C#?","acceptedAnswer":{"@type":"Answer","text":"Creating an ImmutableList from an array of 10,000 elements takes roughly 102,208 nanoseconds versus about 3.4 nanoseconds for wrapping the same list in a ReadOnlyCollection, making ImmutableList creation around 30,000 times slower. This is because ReadOnlyCollection is just a thin wrapper, while ImmutableList copies elements into a new persistent structure. developers weighing immutability against raw speed can track findings like this through daily.dev."}},{"@type":"Question","name":"What is the memory and time cost of updating a FrozenDictionary in .NET?","acceptedAnswer":{"@type":"Answer","text":"Updating a FrozenDictionary requires rebuilding it entirely from a modified source dictionary, since frozen structures cannot be mutated in place. For a 10,000-element dictionary, this rebuild costs about 605,496 nanoseconds and allocates roughly 1,130,445 bytes, compared to near-zero allocation and about 9.77 nanoseconds for an in-place Dictionary update. daily.dev helps developers deciding between dictionary types weigh costs like this rebuild overhead."}}]}
```

