[解決済み] メンバーコレクションを公開するにはReadOnlyCollectionかIEnumerableか?
質問
呼び出し側のコードがコレクションを反復処理するだけなら、内部コレクションを IEnumerable ではなく ReadOnlyCollection として公開する理由はありますか?
class Bar
{
private ICollection<Foo> foos;
// Which one is to be preferred?
public IEnumerable<Foo> Foos { ... }
public ReadOnlyCollection<Foo> Foos { ... }
}
// Calling code:
foreach (var f in bar.Foos)
DoSomething(f);
私の見るところ、IEnumerable は ReadOnlyCollection のインターフェースのサブセットで、ユーザがコレクションを変更することはできません。ですから、もし IEnumerable インターフェースで十分であれば、それを使用することになります。それはそれについて推論する適切な方法ですか、それとも私は何かを見逃していますか?
ありがとうございます/Erik
どのように解決するのですか?
より現代的な解決策
内部コレクションをミュータブルにする必要がなければ
System.Collections.Immutable
パッケージを使い、フィールドの型を変更し、不変のコレクションとし、それを直接公開することができます。
Foo
自体がイミュータブルであると仮定します。
質問をより直接的に扱うために回答を更新しました
<ブロッククオート呼び出し側のコードがコレクションを反復処理するだけなら、内部コレクションをIEnumerableではなくReadOnlyCollectionとして公開する理由はあるでしょうか?
呼び出し側のコードをどの程度信頼しているかによります。もし、このメンバを呼び出すすべてのものを完全に制御していて を保証します。 を使用するコードがないことを保証します。
ICollection<Foo> evil = (ICollection<Foo>) bar.Foos;
evil.Add(...);
であれば、確かにコレクションを直接返すだけなら害はないでしょう。しかし、私は一般的にそれよりも少し偏執的になるようにしています。
同じように、あなたが言うように、もしあなたが
を必要とする
IEnumerable<T>
であるならば、なぜもっと強いものに自分を縛りつけるのか?
元の答え
.NET 3.5を使用している場合、コピーを作成することを避けることができます。 と は Skip の単純な呼び出しを使用することで、単純なキャストを回避できます。
public IEnumerable<Foo> Foos {
get { return foos.Skip(0); }
}
(トリビアルにラップするための他のオプションはたくさんあります。
Skip
の良いところは、反復のたびに無意味に実行するデリゲートがないことです)。
.NET 3.5を使用していない場合は、同じことを行うための非常に簡単なラッパーを書くことができます。
public static IEnumerable<T> Wrapper<T>(IEnumerable<T> source)
{
foreach (T element in source)
{
yield return element;
}
}
関連
-
[解決済み】「The breakpoint will not currently be hit」を改善するには?このドキュメントにはシンボルが読み込まれていません。" という警告はどうすれば改善されますか?
-
[解決済み】スクリプトクラスが見つからないので、スクリプトコンポーネントを追加できない?
-
[解決済み] C#の正しいバージョン番号を教えてください。
-
[解決済み] コンストラクタ内の仮想メンバー呼び出し
-
[解決済み] URLのPath.Combineは?
-
[解決済み] IEnumerable<T> と IQueryable<T> を比較する。
-
[解決済み] IEnumerable<T>のforeachのLINQでの等価性
-
[解決済み] IEnumerable<T> / IQueryable<T>の動的なLINQ OrderBy
-
[解決済み] IEnumerable<T> として単一の項目を渡す
-
[解決済み】IEnumerable vs List - What to Use? どのように動作するのでしょうか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】GDI+、JPEG画像をMemoryStreamに変換する際にジェネリックエラーが発生しました。
-
[解決済み】統合マネージドパイプラインモードで適用されないASP.NETの設定が検出された
-
[解決済み】「入力文字列が正しい形式ではありませんでした」エラーの解決方法は?[重複しています]。
-
[解決済み】非静的メソッドはターゲットを必要とする
-
[解決済み】リソースの読み込みに失敗した:ステータス500(内部サーバーエラー)のサーバーの応答)
-
[解決済み] ...基礎となる接続は閉じられました。予期しないエラーが受信で発生しました
-
[解決済み】 C# 条件演算子エラー 代入、call、increment、decrement、await、new object 式のみ文として使用可能です。
-
[解決済み】Unityでゲームオブジェクトのすべての子をループスルーして破壊する方法?
-
[解決済み】プロセスが実行されているかどうかを知るには?
-
VSでscanfエラーを恒久的に解決するには、ソースファイルを作成し、自動的に#define _CRT_SECURE_NO_WARNINGS 1を追加してください。