List(of T)とCollection(of T)の違いは何ですか?


92

私はそれらが同じように多くの方法で使用されるのを見てきましたが、これをよく理解しないと元に戻せない設計の道を進んでいくのではないかと心配しています。また、私は.NETを使用しています。

回答:


50

Collection<T>はカスタマイズ可能なラッパーIList<T>です。一方でIList<T>密封されていない、それはどんなカスタマイズポイントを提供していません。Collection<T>のメソッドはデフォルトで標準IList<T>メソッドに委譲されていますが、簡単にオーバーライドして必要な処理を実行できます。内部でイベントを関連付けることも可能です。Collection<T>IListで実行できるとは思えないます。

要するに、事実の後でそれを拡張する方がはるかに簡単であり、それは潜在的にはるかに少ないリファクタリングを意味するかもしれません。


@Marc Gravell、@ Adam Lassek:InsertItem(...)メソッドをpublic void new InsertItem(...)で非表示にしてからbase.InsertItem(..を呼び出すことで、Listで同じことを行うことはできません。 。) 内部から ?それでも契約は破られません。(名前はリストでは「挿入」ですが、それでも)。それでは、Collections <T>を使用することの重要な点は何ですか?
DeeStackOverflow 2011年

4
@DeeStackOverflow -を探していること、すなわち何か-メソッドの隠蔽は異なるAPIを使用して任意のコードで使用されることはありませんのでIListIList<T>List<T>など要するに、あなたはそれが呼び出されるかどうかはわかりません。ポリモーフィズムはこれを修正します。
Marc Gravell

@AdamLassek:ObservableCollection<T>変更について通知するためにメソッドがオーバーライドされる例として、回答を追加することができます。
キランチャラ2015年

83

C#には、オブジェクトのバッグを表すための3つの概念があります。機能の増加順に、次のとおりです。

  • 列挙可能 -順不同、変更不可
  • コレクション -アイテムを追加/削除できます
  • リスト -アイテムが注文できるようにします(インデックスによるアクセスと削除)

Enumerableには順序がありません。セットからアイテムを追加または削除することはできません。セット内のアイテムの数を取得することもできません。これにより、セット内の各アイテムに順番にアクセスできます。

コレクションは変更可能なセットです。セットにオブジェクトを追加および削除できます。また、セット内のアイテムの数を取得できます。しかし、まだ順序はありません。順序がないためです。インデックスでアイテムにアクセスする方法も、並べ替える方法もありません。

リストは、順序付けられたオブジェクトのセットです。リストの並べ替え、インデックスによるアイテムへのアクセス、インデックスによるアイテムの削除を行うことができます。

実際、これらのインターフェースを見ると、相互に構築されています。

  • interface IEnumerable<T>

    • GetEnumeration<T>
  • interface ICollection<T> : IEnumerable<T>

    • Add
    • Remove
    • Clear
    • Count
  • interface IList<T> = ICollection<T>

    • Insert
    • IndexOf
    • RemoveAt

変数またはメソッドパラメータを宣言するときは、

  • IEnumerable
  • ICollection
  • IList

概念的には、一連のオブジェクトを処理する必要があります。

リスト内のすべてのオブジェクトに対して何かを実行できるようにする必要がある場合、必要なものはIEnumerable次のとおりです。

void SaveEveryUser(IEnumerable<User> users)
{
    for User u in users
      ...
}

あなたは、ユーザーがに保管されている場合は気にしないList<T>Collection<T>Array<T>または何か他のもの。必要なのはIEnumerable<T>インターフェースだけです。

セット内のアイテムを追加、削除、またはカウントできるようにする必要がある場合は、コレクションを使用します

ICollection<User> users = new Collection<User>();
users.Add(new User());

ソート順を気にし、正しい順序にする必要がある場合は、リストを使用します。

IList<User> users = FetchUsers(db);

グラフ形式:

| Feature                | IEnumerable<T> | ICollection<T> | IList<T> |
|------------------------|----------------|----------------|----------|
| Enumerating items      | X              | X              | X        |
|                        |                |                |          |
| Adding items           |                | X              | X        |
| Removing items         |                | X              | X        |
| Count of items         |                | X              | X        |
|                        |                |                |          |
| Accessing by index     |                |                | X        |
| Removing by indexx     |                |                | X        |
| Getting index of item  |                |                | X        |

これらのインタフェースを実装する2つのクラスがあります。しかし、それらは唯一のクラスではありません:List<T>Collection<T>System.Collections.Generic

  • ConcurrentBag<T>注文されたオブジェクトのバッグです(IEnumerable<T>
  • LinkedList<T>インデックス(ICollection)でアイテムにアクセスできないバッグです。ただし、コレクションにアイテムを任意に追加および削除できます
  • SynchronizedCollection<T> 順序付けられたコレクションで、インデックスによってアイテムを追加/削除できます

したがって、簡単に変更できます。

IEnumerable<User> users = new SynchronizedCollection<User>();

SaveEveryUser(users);

tl; dr

  • 列挙可能 -アイテムへのアクセス、順序付けなし、変更不可
  • コレクション -変更可能(追加、削除、カウント)
  • リスト -インデックスでアクセスできます

必要な概念を選択してから、一致するクラスを使用します。


11
OPが具象型について尋ね、インターフェースを比較しました。具象型Collection <T>はIList <T>を実装し、インデックス機能でアクセスできます。
JJS 2015

2
答えは良いですが、質問から外れています。Collection<T>クラスとList <T>クラスの答えに合わないので、質問の見込みから、正当化されない点を検証しようとすると、一般的な目的の答えとしては、コレクションが順序付けられていないため、インデックスが作成されないが、リストは順序付けされているため、特定のインデックスで挿入が可能であることが正しい場合があります。
Kylo Ren 2016

ICollection <T>の機能を持ち、解決して可能性を見つけようとするとどうなりますか?

2
リストが順序付けられていて、コレクションが順序付けされていない場合、それは機能的に大きな違いがあり、新しい学習者(私のような)が簡単に選択できるようになります。しかし、待ってください、なぜコレクションに秩序がないと言うのですか?IndexOf()メソッドとRemoveAt()メソッドを提供するため、順序付けされているのではないでしょうか。ここで何か見逃しましたか?
RayLuo 2017年

1
@RayLuoとを具体的に参照しICollection<T>ていIList<T>ます。具象実装が異なると、動作が異なる場合があります。たとえばList<T>IEnumerable<T>インターフェースを介してにアクセスする場合、リスト内のアイテムを追加、削除、並べ替え、またはカウントする方法はありません。
Ian Boyd

43

List<T>アプリケーションコード内での内部使用を目的としています。受け入れるまたは返すパブリックAPIの記述は避けてくださいList<T>(代わりにスーパークラスまたはコレクションインターフェイスの使用を検討してください)。

Collection<T> カスタムコレクションの基本クラスを提供します(直接使用できます)。

必要Collection<T>な特定の機能がない限り、コードでの使用を検討してくださいList<T>

上記は単なる推奨事項です。

[改訂:フレームワーク設計ガイドライン、第2版]


問題のオブジェクトが変更されたときに所有者に通知する手段がない場合、またはメソッドを返すメソッドの名前がない場合を除き、独自の状態をカプセル化するために任意の種類の可変オブジェクトを使用する型は、そのような型のオブジェクトを返さないようにする必要があります。オブジェクトは、新しいインスタンスを返すことを意味します。たとえば、ディクショナリの状態は、内容ではなくリストのIDのみをカプセル化するため、戻り値は問題ありません。Dictionary<string, List<string>>List<string>
スーパーキャット2013

37

List<T>それは(のような便利なメソッドの多くで非常に汎用性の高いそうですので、非常によく見られるコンテナであるSortFindなど、) -しかし、あなたは(たとえば、挿入上の項目を確認してください)動作のいずれかを上書きしたい場合は何の拡張ポイントを持っていません。

Collection<T>はすべてのラッパーですIList<T>(デフォルトはList<T>)-拡張ポイント(virtualメソッド)がありますが、などのサポートメソッドほど多くはありませんFind。間接的なため、は少し遅いですがList<T>、それほどではありません。

LINQ、中にメソッドを追加したList<T>あまり重要になって、LINQツーオブジェクトは、とにかくそれらを提供する傾向があるため...例えばFirst(pred)OrderBy(...)など


6
Linq-to-Objectsでも、Collection <T>にはメソッドforeachがありません。
tuinstoel 2008

7
@tuinstoel-追加するのは簡単です。
Marc Gravell

12

リストはより高速です。

例えば

private void button1_Click(object sender, EventArgs e)
{
  Collection<long> c = new Collection<long>();
  Stopwatch s = new Stopwatch();
  s.Start();
  for (long i = 0; i <= 10000000; i++)
  {
    c.Add(i);
  }
  s.Stop();
  MessageBox.Show("collect " + s.ElapsedMilliseconds.ToString());

  List<long> l = new List<long>();
  Stopwatch s2 = new Stopwatch();
  s2.Start();
  for (long i = 0; i <= 10000000; i++)
  {
    l.Add(i);
  }
  s2.Stop();
  MessageBox.Show("lis " + s2.ElapsedMilliseconds.ToString());


}

私のマシンでList<>は、ほぼ2倍の速度です。

編集する

なぜ人々がこれに反対票を投じているのか理解できません。私の仕事用マシンと自宅用マシンの両方で、List <>コードは80%高速です。


1
どのように速くなりますか?調べる?挿入?除去?探す?なぜそれが速いのですか?
Doug T.

17
リストは、コレクションよりも入力する文字が少ない:)
RedFilter 2008

1
コレクションにはメソッドが少ない。したがって、それはより高速です。QED。(冗談です、私はトローリングをしていません)
Ray

2
私のマシンで試してみたところ、リストは約20%速くなりました。これがなぜであるかについての議論に興味があります。たぶん、リストはメモリを割り当てる方が良いでしょう。
レイ

10
Listのメソッドは継承できないため、継承されているかどうかを確認するチェックはありません。コレクションのメソッドは継承可能です。利点は、コレクションを基本クラスとして使用して、カスタムコレクションを継承および作成できることです。
Richard Gadsden

11

リストは、アイテムの順序が重要なコレクションを表します。また、並べ替えと検索のメソッドもサポートしています。コレクションはより一般的なデータ構造であり、データに関する仮定が少なく、データを操作するためのメソッドも少なくなっています。カスタムデータ構造を公開する場合は、コレクションを拡張する必要があります。データ構造を公開せずにデータを操作する必要がある場合は、リストの方がおそらく便利です。


4

これは大学院の質問の1つです。Tのコレクションは一種の抽象的です。デフォルトの実装があるかもしれませんが(私は.net / c#の人ではありません)、コレクションには追加、削除、反復などの基本的な操作があります。

Tのリストは、これらの操作に関するいくつかの詳細を示しています。追加には一定の時間がかかり、削除には要素の数に比例した時間がかかり、getfirstは一定の時間である必要があります。一般に、リストは一種のコレクションですが、コレクションは必ずしも一種のリストであるとは限りません。


4

Hanselman Speaks:「Collection<T>リストのように見え、List<T>内部にもあります。単一のメソッドList<T>はすべて内部に委譲します。これは、を公開する保護されたプロパティを含みList<T>ます。」

編集: Collection<T>System.Generic.Collections .NET 3.5には存在しません。.NET 2.0から3.5に移行する場合、多くのCollection<T>オブジェクトを使用している場合は、明らかなものがない限り、コードを変更する必要があります...

編集2:Collection<T>.NET 3.5のSystem.Collections.ObjectModel名前空間に追加されました。ヘルプファイルはこれを言います:

「System.Collections.ObjectModel名前空間には、再利用可能なライブラリのオブジェクトモデルでコレクションとして使用できるクラスが含まれています。これらのクラスは、プロパティまたはメソッドがコレクションを返すときに使用します。」


4

これらのインターフェースはすべてから継承しているためIEnumerable、理解しておく必要があります。そのインターフェイスでは、基本的にクラスをforeachステートメント(C#)で使用できます。

  • ICollectionリストしたインターフェースの中で最も基本的なものです。これは、をサポートする列挙可能なインターフェースでありCount、それについてです。
  • IListそれがすべてですICollectionが、アイテムの追加と削除、インデックスによるアイテムの取得などもサポートします。これは、「オブジェクトのリスト」で最もよく使用されるインターフェースです。
  • IQueryableLINQをサポートする列挙可能なインターフェースです。IQueryableIListからを作成してLINQ to Objectsを使用できますがIQueryable、LINQ to SQLおよびLINQ to EntitiesのSQLステートメントの遅延実行にも使用できます。
  • IDictionary一意のキーと値のマッピングであるという意味で、別の動物です。キーと値のペアを列挙できるという点でも列挙可能ですが、それ以外の場合は、リストした他の目的とは異なる目的を果たします

ICollectionをサポートの追加/削除/クリア:msdn.microsoft.com/en-us/library/...
記憶喪失

4

MSDNによれば、List(Of T).Addは「O(n)操作」(「容量」を超えた場合)であり、Collection(Of T).Addは常に「O(1)操作」です。リストが配列とリンクされたリストのコレクションを使用して実装されている場合、それは理解できるでしょう。ただし、その場合は、Collection(Of T).Itemが「O(n)操作」であると想定されます。しかし-それは- じゃない!?!Collection(Of T).Itemは、List(Of T).Itemと同様に「O(1)操作」です。

その上、上記の「tuinstoel」の「12月29日08:22:31」の投稿では、速度テストはList(Of T).AddがCollection(Of T).Addよりも高速であることを示していると主張しています。ロングとストリング。MSDNによると、私は彼の主張する80%に比べて33%速くなっただけですが、それは反対で「n」倍だったはずです!?!


3

どちらも同じインターフェースを実装しているため、同じように動作します。多分それらは内部で異なって実装されますが、これはテストする必要があります。

私が目にする唯一の実際の違いは、名前空間とCollection<T>でマークされている事実です。そのComVisibleAttribute(false)ため、COMコードはそれを使用できません。


それらは異なるインターフェイスを実装します-List <T>はIList <T>を実装しますが、Collection <T>は実装しません。
Bevan

@Bevanはc#で試してみます。どちらも同じインターフェイスのセットを実装しています
Kylo Ren

1
それは興味深い変更@KyloRenだ-彼らはない今、両方のインターフェイスの同じセットを実装します。これは、2008年には当てはまりませんでした。
Bevan 2016年

1
@Bevan面白い。2つの異なるクラスの理由が何かはわかりません。1つはいくつかの追加のメソッドのみです。
Kylo Ren 2016

3

他の質問に加えて、一般的なリストと収集機能の概要をまとめました。コレクションはリストの限られたサブセットです:

* = プレゼント 
o = 部分的に存在

プロパティ/ メソッドコレクション< T > リスト< T > --------------------------------------- -------      

Add()                *              *
AddRange()                          *
AsReadOnly()                        *
BinarySearch()                      *
Capacity                            *
Clear()              *              *
Contains()           *              *
ConvertAll()                        *
CopyTo()             o              *
Count                *              *
Equals()             *              *
Exists()                            *
Find()                              *
FindAll()                           *
FindIndex()                         *
FindLast()                          *
FindLastIndex()                     *
ForEach()                           *
GetEnumerator()      *              *
GetHashCode()        *              *
GetRange()                          *
GetType()            *              *
IndexOf()            o              *
Insert()             *              *
InsertRange()                       *
Item()               *              *
LastIndexOf()                       *
New()                o              *
ReferenceEquals()    *              *
Remove()             *              *
RemoveAll()                         *
RemoveAt()           *              *
RemoveRange()                       *
Reverse()                           *
Sort()                              *
ToArray()                           *
ToString()           *              *
TrimExcess()                        *
TrueForAll()                        *
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.