TIL: ImmutableArray vs FrozenSet en .NET 8
Descubrí hoy que FrozenSet tiene lookups O(1) optimizados para colecciones creadas una vez y consultadas muchas veces, al contrario que ImmutableHashSet que sacrifica rendimiento por inmutabilidad pura.
TL;DR
FrozenSet es para 'read many, write never'. ImmutableHashSet es para 'safe concurrency + occasional writes'. Elige según el patrón de acceso.
Índice
Today I Learned que FrozenSet<T> y ImmutableHashSet<T> no son intercambiables aunque ambos sean inmutables.
La diferencia clave
// ImmutableHashSet — inmutable, pero con overhead de versioning estructural
var immutable = ImmutableHashSet.Create("foo", "bar", "baz");
// FrozenSet — optimizado para lookups, sin overhead de modificación
var frozen = FrozenSet.ToFrozenSet(new[] { "foo", "bar", "baz" });
FrozenSet construye una estructura interna al crearse (más lento en construcción) pero luego los Contains() son notablemente más rápidos. Ideal para colecciones de configuración, listas de allowed values, o cualquier cosa que se inicialice una vez al arranque.
Benchmark rápido (BenchmarkDotNet)
| Método | Media |
|---|---|
| HashSet.Contains | 12.3 ns |
| ImmutableHashSet.Contains | 18.7 ns |
| FrozenSet.Contains | 8.1 ns |
Cuándo usar cada uno
HashSet: lookups en hot path sin requisito de inmutabilidad.ImmutableHashSet: cuando necesitas pasar colecciones entre threads con garantías de no modificación.FrozenSet: configuración de arranque, lookup-heavy, tamaño conocido y estable.