web-dev-qa-db-ja.com

C#で読み取り専用配列を作成する最良の方法は何ですか?

私のプロパティから読み取り専用配列を返したいという非常にありそうもない、元の状況があります。これまでのところ、私はそれを行う1つの方法のみを知っています-System.Collections.ObjectModel.ReadOnlyCollection<T>。しかし、それはどういうわけか私には扱いにくいようです。 このクラスは、インデックスによって配列要素にアクセスする機能を失うことは言うまでもありません (追加:おっと、インデクサーを逃した)。より良い方法はありませんか?配列自体を不変にすることができる何か?

48
Vilx-

_ReadOnlyCollection<T>_ を使用します。それは読み取り専用であり、あなたが信じていることに反して、それはインデクサーを持っています。

配列は不変ではなく、_ReadOnlyCollection<T>_のようなラッパーを使用せずに配列を変更する方法はありません。

_ReadOnlyCollection<T>_ラッパーの作成はO(1)オペレーションであり、パフォーマンスコストは発生しません。

更新
他の回答は、コレクションを新しい _IReadOnlyList<T>_ にキャストすることを提案しています。これは_IReadOnlyCollection<T>_を拡張してインデクサーを追加します。残念ながら、元のコレクションタイプにキャストバックして変更できるため、コレクションの可変性を実際に制御することはできません。

代わりに、_ReadOnlyCollection<T>_(_List<T>_メソッド AsReadOnly() 、またはArrays静的メソッド AsReadOnly() は、リストと配列を適宜ラップするのに役立ちます)、コレクションへの不変のアクセスを作成し、それを直接、または_IReadOnlyList<T>_を含むサポートするインターフェースのいずれかとして公開します。

47
Jeff Yates

.NET Framework 4.5では、IReadOnlyList<T>から拡張されたIReadOnlyCollection<T>が導入され、T this[int index] { /*..*/ get; }が追加されました。

T[]からIReadOnlyList<T>にキャストできます。これの1つの利点は、(IReadOnlyList<T>)arrayarrayに当然等しいことです。ボクシングは含まれません。

もちろん、ラッパーが使用されていないので、(T[])GetReadOnlyList()は変更可能です。

10
Warty

.NET Framework 2.0以降には Array.AsReadOnly があり、自動的に ReadOnlyCollection ラッパーが作成されます。

6
N8allan

本当に配列を返したいが、配列のコンシューマーが内部データを混乱させるのではないかと心配している場合は、配列のコピーを返すだけです。個人的にはまだReadOnlyCollection<T>が先ですが、もし[〜#〜] really [〜#〜]配列が必要な場合は.....

5
BFree

IEnumerableが思い浮かびます。

1
epitka

IEnumerableインターフェイスを実装し、this [int]演算子をオーバーロードして、そのセッターへのアクセスを拒否することができます。

0
Morfildur

イミュータブルコレクションがサポートされるようになりました。 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
Henry