ReadOnlySet<T> в .NET 9
Очередная, шестая, превью версия .NET 9 представит новый тип ReadOnlySet<T>. Это множество только для чтения, аналогичное ReadOnlyCollection<T>. Посмотрим, как это работает и зачем оно добавлено.
IReadOnlySet недостаточно
У нас уже есть интерфейс IReadOnlySet<T>. Например, его реализует FrozenSet. Почему его недостаточно? Рассмотрим List<T> и IReadOnlyList<T>, которые страдают от той же проблемы:
var list = new List<int> { 1, 2, 3 };
IReadOnlyList<int> readOnlyList = list;
// Вы можете привести это обратно к List<T> и изменить
var list2 = (List<int>)readOnlyList;
list2.Add(4);
Console.WriteLine($"List: {list.Count}");
Console.WriteLine($"ReadOnlyList: {readOnlyList.Count}");
Console.WriteLine($"List2: {list2.Count}");Вывод (внезапно):
List: 4
ReadOnlyList: 4
List2: 4
Конечно, потребителям вашего API не следует этого делать, но вы не можете этого предотвратить. Вот почему у нас есть AsReadOnly:
List<int> list = [1, 2, 3];
var readOnlyList = list.AsReadOnly();
// Вы не можете привести это к List<T>
var list2 = (List<int>)readOnlyList; // Исключение
AsReadOnly возвращает ReadOnlyCollection<T>, поэтому приведение её к изменяемому списку невозможно.
Той же проблемой страдает и IReadOnlySet<T>. Именно для этого создан ReadOnlySet<T>:
var set = new HashSet<int> { 1, 2, 3 };
var readonlySet = new ReadOnlySet<int>(set);Неправильный обходной путь
Если попытаться реализовать собственный способ создания множества только для чтения, пришлось бы создать что-то вроде ImmutableHashSet<T> или FrozenSet.
var set = new HashSet<int> { 1, 2, 3 };
var readOnly = set.ToFrozenSet(); // или ToImmutableHashSet()Хотя технически это работает, у этого две основные проблемы:
1. Неизменяемые коллекции, такие как ImmutableHashSet<T> или FrozenSet, должны cкопировать всю коллекцию в свою память, чтобы гарантировать неизменяемость. Это может быть пустой тратой памяти и циклов процессора.
2. Это не совсем множество только для чтения. «Только для чтения» и «неизменяемый» — это два разных понятия, как мы разобрали недавно.
Подробнее о предложении новинки тут.
Источник: https://steven-giesel.com/blogPost/f368c7d3-488e-4bea-92b4-abf176353fa3/readonlysett-in-net-9