web-dev-qa-db-ja.com

「IList」対「ICollection」対「Collection」を返す

パブリックAPIのメソッドとプロパティからどのコレクションタイプを返すかについて混乱しています。

私が念頭に置いているコレクションは、IListICollection、およびCollectionです。

これらのタイプのいずれかを返すことは常に他のタイプよりも優先されますか、それとも特定の状況に依存しますか?

105
Rocky Singh

一般に、可能な限り一般的な型、つまり、消費者が使用する必要がある返されたデータを十分に把握している型を返す必要があります。そうすれば、使用しているコードを壊すことなく、APIの実装を自由に変更できます。

戻り型としてIEnumerable<T>インターフェイスも考慮してください。結果が繰り返されるだけの場合、消費者はそれ以上を必要としません。

66
Guffa

ICollection<T>は、Add()Remove()Countなどのコレクションセマンティクスを公開するインターフェイスです。

Collection<T>は、ICollection<T>インターフェイスの具体的な実装です。

IList<T>は基本的に、ランダムな順序ベースのアクセスを備えたICollection<T>です。

この場合、結果に順序ベースのインデックス付けなどのリストセマンティクスが必要か(IList<T>を使用)、または順序付けられていない「バッグ」の結果を返すだけか(ICollection<T>を使用)を決定する必要があります)。

128
cordialgerm

IList<T>ICollection<T>の主な違いは、IList<T>を使用すると、インデックスを介して要素にアクセスできることです。 IList<T>は、配列のような型を記述します。 ICollection<T>の要素には、列挙を介してのみアクセスできます。どちらも要素の挿入と削除を許可します。

コレクションのみを列挙する必要がある場合は、IEnumerable<T>が優先されます。それは他のものに比べて2つの利点があります:

  1. コレクションへの変更を禁止します(参照オブジェクトの場合、参照オブジェクトの場合は変更できません)。

  2. アルゴリズムによって生成され、コレクションではない列挙を含む、可能な限り多様なソースを使用できます。

Collection<T>は、主にコレクションの実装者に役立つ基本クラスです。インターフェイス(API)で公開すると、派生していない多くの有用なコレクションが除外されます。


IList<T>の欠点の1つは、配列がそれを実装しているが、アイテムを追加または削除できないことです(つまり、配列の長さを変更することはできません)。配列でIList<T>.Add(item)を呼び出すと、例外がスローされます。 IList<T>にはブールプロパティIsReadOnlyがあり、これを試みる前に確認できるため、状況は多少緩和されます。 しかし、私の目には、これはまだライブラリの設計上の欠陥です。したがって、アイテムを追加または削除する必要がある場合は、List<T>を直接使用します。

IList<T>は、すべての汎用リストの基本インターフェースです。順序付けられたコレクションであるため、実装は、ソートされた順序から挿入順序に至るまで、順序付けを決定できます。さらに、Ilistには、メソッドがインデックスに基づいてリスト内のエントリを読み取り、編集できるようにするItemプロパティがあります。これにより、位置インデックスでリストに値を挿入したり、リストから値を削除したりできます。

また、IList<T> : ICollection<T>以降、ICollection<T>のすべてのメソッドも実装に利用できます。

ICollection<T>は、すべてのジェネリックコレクションの基本インターフェイスです。サイズ、列挙子、同期方法を定義します。コレクションにアイテムを追加または削除することはできますが、インデックスプロパティが存在しないため、アイテムが発生する位置を選択することはできません。

Collection<T>は、IList<T>IList、およびIReadOnlyList<T>の実装を提供します。

ICollection<T>の代わりにIList<T>などのより狭いインターフェイスタイプを使用すると、重大な変更からコードを保護できます。 IList<T>などのより広いインターフェイスタイプを使用すると、コードの変更を壊す危険性が高まります。

source から引用

ICollectionICollection<T>:コレクションを変更するか、コレクションのサイズを気にします。 IListIList<T>:コレクションを変更する場合、コレクション内の要素の順序や位置を気にします。

6
NullReference

インターフェイスタイプを返すのがより一般的であるため、(特定のユースケースに関する詳細情報はありません)私はそれに傾いています。インデックス作成のサポートを公開する場合は、IList<T>を選択します。そうでない場合は、ICollection<T>で十分です。最後に、返された型が読み取り専用であることを示す場合は、IEnumerable<T>を選択します。

また、Brad AbramsとKrzysztof Cwalinaがまだ読んでいない場合に備えて、「Framework Design Guidelines:Conventions、Idioms、and Patterns for Reusable .NET Libraries」というタイトルの素晴らしい本を書いています(ダイジェストは here )。

4
Alan