Заморозили и полетело: всё, что нужно знать про Frozen-коллекции в C#

Привет, Хабр!
В проде полно таблиц и маппингов, которые создаются один раз и потом живут годами на чистом чтении. Раньше выбирали между ReadOnlyDictionary и Immutable*. Первый не ускоряет доступ и просто прикрывает исходную коллекцию, второй дает чистые апдейты, но платит временем построения и lookup. В .NET 8 появился третий путь для такого профиля: System.Collections.Frozen.
Задача у Frozen простая и приземленная. Заплатить за построение структуры один раз на старте, а дальше получать быстрый TryGetValue/Contains и предсказуемое перечисление без блокировок. Контейнер неизменяемый, потокобезопасен для чтения и специально заточен под lookup. Стоимость сборки выше обычной, это ожидаемо, поэтому применять его есть смысл там, где чтений на порядки больше, чем конструирований.
С .NET 9 стало еще удобнее: появился alternate lookup. Теперь словарь со строковыми ключами может принимать ReadOnlySpan<char> прямо на lookup, без лишних аллокаций. Это хорошо заходит в веб-пути, парсеры заголовков и любые сценарии, где строка у вас уже как span.