プライベートコレクションを呼び出し元に返すメソッドがあり、呼び出し元が返されたコレクションを変更できないようにしたい。
private readonly Foo[] foos;
public IEnumerable<Foo> GetFoos()
{
return this.foos;
}
現時点ではプライベートコレクションは固定配列ですが、実行時に新しいアイテムを追加する必要が生じた場合、将来的にコレクションがリストになる可能性があります。
呼び出し元がコレクションを変更できないようにするための解決策がいくつかあります。戻りIEnumerable<T>
値は最も簡単な解決策ですが、呼び出し元は戻り値をコレクションにアップキャストしてIList<T>
変更することができます。
((IList<Foo>)GetFoos())[0] = otherFoo;
コレクションのクローンを作成することには、独立して進化できる2つのコレクションがあるという明らかな欠点があります。これまで、次のオプションを検討してきました。
- コレクションをでラップし
ReadOnlyCollection<T>
ます。 Enumerable
のようなダミーの射影を実行することにより、クラスによって定義されたLINQイテレータの1つを返しますlist.Select(item => item)
。Where(item => true)
返されたイテレータの方が軽量に見えるので、実際に使用することを検討します。- カスタムラッパーを作成します。
私が使用するのが好きではないのReadOnlyCollection<T>
は、それが実装されており、インデクサーをIList<T>
呼び出しAdd()
たりアクセスしたりすると例外が発生することです。これは理論的には絶対に正しいですが、実際のコードチェックIList<T>.IsReadOnly
やIList<T>.IsFixedSize
。
LINQイテレータを使用すると(コードを拡張メソッドでラップしましたMakeReadOnly()
)、このシナリオを防ぐことができますが、ハックのような味がします。
カスタムラッパーを作成しますか?車輪の再発明?
考え、考慮事項、またはその他の解決策はありますか?
この質問にタグを付けているときに、以前は気づかなかったこのStackOverflowの質問を発見しました。Jon Skeetも「LINQハック」を使用することを提案していますが、を使用するとさらに効率的Skip(0)
です。