メソッド呼び出し元が返されたコレクションを変更するのを防ぐ方法は? [複製]
-
10-07-2019 - |
質問
この質問にはすでに回答があります:
プライベートコレクションを呼び出し元に返すメソッドがあり、呼び出し元が返されたコレクションを変更できないようにしたい。
private readonly Foo[] foos;
public IEnumerable<Foo> GetFoos()
{
return this.foos;
}
現時点では、プライベートコレクションは固定配列ですが、実行時に新しいアイテムを追加する必要が生じた場合、将来コレクションはリストになる可能性があります。
発信者がコレクションを変更するのを防ぐための解決策がいくつかあります。 IEnumerable<T>
を返すことが最も簡単な解決策ですが、呼び出し元は戻り値をIList<T>
にアップキャストしてコレクションを変更できます。
((IList<Foo>)GetFoos())[0] = otherFoo;
コレクションの複製には、独立して進化できるコレクションが2つあるという明らかな欠点があります。これまでのところ、次のオプションを検討しました。
-
ReadOnlyCollection<T>
でコレクションをラップします。 -
Enumerable
などのダミー投影を実行して、list.Select(item => item)
クラスで定義されたLINQイテレータの1つを返します。実際、返されるイテレータはより軽量に見えるため、Where(item => true)
の使用を検討します。 - カスタムラッパーの作成
Add()
の使用に関して気に入らないのは、IList<T>.IsReadOnly
を実装し、IList<T>.IsFixedSize
を呼び出すか、インデクサーにアクセスすると例外が発生することです。これは理論上は完全に正しいですが、MakeReadOnly()
またはSkip(0)
をチェックする実際のコードはほとんどありません。
LINQイテレータの使用-拡張メソッドでコードをラップ<=>-このシナリオを防ぎますが、ハッキングの味があります。
カスタムラッパーの作成車輪を再発明しますか?
考え、考慮事項、または他の解決策はありますか?
この質問にタグを付けている間に、このスタックオーバーフローの質問を発見しました以前は気づかなかった。 Jon Skeetは、<!> quot; LINQ hack <!> quot;も使用することを提案していますが、<=>を使用するとさらに効率的です。
解決
残念ながら、現在のバージョンのフレームワークで探しているものを正確に達成する方法はありません。具体的な型とインターフェーススタイルの両方で、インデックス可能な不変/読み取り専用のコレクションという概念はありません。
あなたが指摘したように、ReadOnlyCollection<T>
は具象型側で問題なく機能します。しかし、静的に読み取り専用である、実装する対応するインターフェースはありません。
あなただけが本当の選択です...
- 独自のコレクションクラスを定義する
-
IEnumerable<T>
のみを実装するか、コレクションが実装する必要な読み取り専用インターフェイスを定義します。
他のヒント
返されるオブジェクトのディープコピーを作成する方法は? [そのため、呼び出し元が返されたコピーに変更を加えることを決定した場合でも、元のコレクションに影響はありません]
リストと配列にはAsReadOnlyメソッドがあります:
public IEnumerable<Foo> GetFoos()
{
return Array.AsReadOnly(this.foos);
// or if it is a List<T>
// return this.foos.AsReadOnly();
}
このような場合、クラス内のメソッドを作成して、プライベートコレクションの個々の要素にアクセスします。 インデクサー( http://msdn.microsoft.com/en- us / library / 6x16t2tx.aspx )プライベートコレクションを含むクラス。