У меня очень маловероятная и оригинальная ситуация, когда я хочу вернуть массив readonly из моего свойства. Пока я знаю только один способ сделать это - через System.Collections.ObjectModel.ReadOnlyCollection<T>
. Но мне это кажется неудобным, не говоря уже о том, что этот класс теряет возможность доступа к элементам массива по индексу (добавил: whoops, я пропустил индексатор). Нет ли лучшего способа? Что-то, что может сделать массив неизменным?
Каков наилучший способ создания массива readonly в С#?
Ответ 1
Используйте ReadOnlyCollection<T>
. Он доступен только для чтения и, вопреки тому, что вы считаете, имеет указатель.
Массивы не являются неизменяемыми, и их невозможно сделать без использования обертки, например ReadOnlyCollection<T>
.
Обратите внимание, что создание обертки ReadOnlyCollection<T>
является операцией O (1) и не несет каких-либо затрат на производительность.
Обновление
Другие ответы предложили просто набросать коллекции на новый IReadOnlyList<T>
, который расширяет IReadOnlyCollection<T>
для добавления индексатора. К сожалению, это фактически не дает вам контроля над изменчивостью коллекции, поскольку она может быть отброшена в исходный тип коллекции и изменена.
Вместо этого вы все равно должны использовать метод ReadOnlyCollection<T>
(List<T>
AsReadOnly()
или Array
статический метод AsReadOnly()
помогает связать списки и массивы соответственно), чтобы создать неизменный доступ к коллекции, а затем разоблачить это либо напрямую, либо как любой из интерфейсов он поддерживает, включая IReadOnlyList<T>
.
Ответ 2
В .NET Framework 4.5 представлен IReadOnlyList<T>
, который простирается от IReadOnlyCollection<T>
, добавляя T this[int index] { /*..*/ get; }
.
Вы можете использовать от T[]
до IReadOnlyList<T>
. Одним из преимуществ этого является то, что (IReadOnlyList<T>)array
понятно равно array
; бокс не участвует.
Конечно, поскольку оболочка не используется, (T[])GetReadOnlyList()
будет изменяться.
Ответ 3
Если вы действительно хотите вернуть массив, но опасаетесь, что потребитель массива будет работать с внутренними данными, просто верните копию массива. Лично я все еще думаю, что ReadOnlyCollection<T>
- это путь, но если вы ДЕЙСТВИТЕЛЬНО хотите массив.....
Ответ 4
Из .NET Framework 2.0 и выше Array.AsReadOnly, который автоматически создает ReadOnlyCollection для вас.
Ответ 5
IEnumerable приходит на ум.
Ответ 6
Возможно, вы захотите реализовать интерфейс IEnumerable и перегрузить этот оператор [int], чтобы запретить доступ к нему setter