Каков наилучший способ создания массива только для чтения в C #? - PullRequest
44 голосов
/ 25 января 2010

У меня крайне маловероятная и оригинальная ситуация, когда я хочу вернуть массив только для чтения из моего свойства. До сих пор я знаю только один способ сделать это - через System.Collections.ObjectModel.ReadOnlyCollection<T>. Но это кажется мне несколько неловким, не говоря уже о том, что этот класс теряет возможность доступа к элементам массива по их индексу ( добавлено: упс, я пропустил индексатор ). Нет лучшего способа? Что-то, что могло бы сделать сам массив неизменным?

Ответы [ 7 ]

47 голосов
/ 25 января 2010

Использование ReadOnlyCollection<T>. Он доступен только для чтения и, вопреки вашему мнению, имеет индексатор.

Массивы не являются неизменяемыми, и их невозможно создать без использования оболочки типа ReadOnlyCollection<T>.

Обратите внимание, что создание оболочки ReadOnlyCollection<T> является операцией O (1) и не приводит к снижению производительности.

Обновление
Другие ответы предлагали просто привести коллекции к более новому IReadOnlyList<T>, что расширяет IReadOnlyCollection<T> для добавления индексатора. К сожалению, это фактически не дает вам контроля над изменчивостью коллекции, поскольку она может быть возвращена к исходному типу коллекции и видоизменена.

Вместо этого вы все равно должны использовать ReadOnlyCollection<T> (метод List<T> AsReadOnly() или Array s статический метод AsReadOnly() помогает обернуть списки и соответственно) для создания неизменяемого доступа к коллекции и последующего ее предоставления либо напрямую, либо в качестве любого из поддерживаемых интерфейсов, включая IReadOnlyList<T>.

10 голосов
/ 19 декабря 2013

.NET Framework 4.5 представила IReadOnlyList<T>, который простирается от IReadOnlyCollection<T> с добавлением T this[int index] { /*..*/ get; }.

Вы можете разыграть от T[] до IReadOnlyList<T>. Одним из преимуществ этого является то, что (IReadOnlyList<T>)array по понятным причинам равняется array; бокс не участвует.

Конечно, поскольку оболочка не используется, (T[])GetReadOnlyList() будет изменяемым.

6 голосов
/ 27 сентября 2013

Начиная с .NET Framework 2.0 и выше Array.AsReadOnly автоматически создает обертку ReadOnlyCollection .

5 голосов
/ 25 января 2010

Если вы действительно хотите, чтобы массив возвращался, но боитесь, что потребитель массива будет связываться с внутренними данными, просто верните копию массива. Лично я все еще думаю, что ReadOnlyCollection<T> - это путь, но если вам ДЕЙСТВИТЕЛЬНО нужен массив .....

1 голос
/ 25 января 2010

IEnumerable приходит на ум.

0 голосов
/ 29 августа 2018

Теперь есть поддержка неизменяемых коллекций. Смотри https://www.nuget.org/packages/System.Collections.Immutable

Поддерживается любое из следующего:

  • .NET 4.5 (или выше)
  • .NETStandard 1.0 (или выше)
  • Windows 8.0
  • WindowsPhone 8.0
  • WindowsPhoneApp 8.1
  • Переносимая библиотека классов (.NETFramework 4.5, Windows 8.0, WindowsPhone 8.0, WindowsPhoneApp 8.1)
0 голосов
/ 25 января 2010

Возможно, вы захотите реализовать интерфейс IEnumerable и перегрузить оператор this [int], чтобы запретить доступ к его установщику

...