.NET のコレクションついて再確認する

# .NETのコレクションに関するおさらい

.NETでは、用途に応じた様々なコレクションクラスが用意されています。
.NETの進化に合わせて、追加されたクラスやインターフェイスもありますが、まとまった知識として追い切れていませんでした。
そこで、.NET5.0(C#9)となった現在（2021年5月）、改めて.NETのコレクションについておさらいしてみたいと思います。

※今回は、必要な情報にたどり着くためのインデックス的なページとしました。
個々のトピックについては、今後個別に取り上げていきたいと思います。

- [等価性比較のインターフェイス`IEquatable<T>` と `IEqualityComparer<T>`について](https://qiita.com/pierusan2010/items/636b24a190b3999d5993)
- (予定)`IComparable<T>`と`IComparer<T>`について

# System.Collections から始まる名前空間

ここでは、`System.Collections`で始まる名前空間について、定義されている主要なインターフェイスとクラスについて確認します。

## System.Collections 名前空間
>Microsoft Docs: https://docs.microsoft.com/ja-jp/dotnet/api/system.collections?view=net-5.0
リスト、キュー、ビット配列、ハッシュ テーブル、ディクショナリなど、オブジェクトのさまざまなコレクションを定義するインターフェイスとクラスが含まれています。

こちらは、互換性のためだけに残っている遺物です。
可能な限り`System.Collections.Generic`名前空間のコレクションを利用するようにしましょう。

## System.Collections.Generic 名前空間
>Microsoft Docs: https://docs.microsoft.com/ja-jp/dotnet/api/system.collections.generic?view=net-5.0
ジェネリック コレクションを定義するインターフェイスとクラスが含まれています。このコレクションを使用することにより、ユーザーは、汎用的でない厳密に型指定されたコレクションに比べてタイプ セーフでパフォーマンスが高い、厳密に型指定されたコレクションを作成できるようになります。		

ここでは、コレクションを操作するためのインターフェイスと、基本的なコレクションクラス群が定義されています。

### 要素の比較をサポートするインターフェイス

コレクションの並び替えや、要素の同値性を調べる際に利用するインターフェースが定義されています。

|インターフェイス|説明|
|--|--|--|
|`IEqualityComparer<T>`|オブジェクトの等価比較をサポートするメソッドを定義します。|
|`IComparer<T>`|2 つのオブジェクトを比較するために型が実装するメソッドを定義します。|

### イテレーションを提供するインターフェイス
主にforeach 文をサポートするためのインターフェイス `IEnumerable<T>` と `IEnumerator<T>`が定義されています。
また、LINQ to Object の拡張メソッド群は　`IEnumerable<T>` のメソッドとして定義されています。

C#8.0からは、非同期foreachをサポートするためのインターフェイス `IAsyncEnumerable<T>` と `IAsyncEnumerator<T>` が追加されています。

- [非同期ストリームの生成と使用 | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/csharp/whats-new/tutorials/generate-consume-asynchronous-stream)

|インターフェイス|説明|
|--|--|--|
|`IEnumerable<T>`|指定した型のコレクションに対する単純な反復処理をサポートする列挙子を公開します。|
|`IEnumerator<T>`|ジェネリック コレクションに対する単純な反復処理をサポートします。|
|`IAsyncEnumerable<T>`|指定した型の値に対して非同期イテレーションを提供する列挙子を公開します。|
|`IAsyncEnumerator<T>`|ジェネリック コレクションに対する単純な非同期イテレーションをサポートします。|

### 各種コレクションを表現するインターフェイス

`IList<T>`や`IDictionary<TKey,TValue>`など、コレクションの基本的な操作を行うインターフェイスが定義されています。
また、`IReadOnlyCollection<T>`などの読み取り専用コレクションを表すインターフェイスも定義されています。

|インターフェイス|説明|
|--|--|--|
|`ICollection<T>`|ジェネリック コレクションを操作するメソッドを定義します。|
|`IDictionary<TKey,TValue>`|キーと値のペアのジェネリック コレクションを表します。|
|`IList<T>`|インデックスによって個別にアクセスできるオブジェクトのコレクションを表します。|
|`ISet<T>`|セットの抽象化のための基底インターフェイスを提供します。|
|`IReadOnlyCollection<T>`|要素の厳密に型指定された読み取り専用のコレクションを表します。|
|`IReadOnlyDictionary<TKey,TValue>`|キーと値のペアの読み取り専用ジェネリック コレクションを表します。|
|`IReadOnlyList<T>`|インデックスによってアクセスできる要素の読み取り専用コレクションを表します。|
|`IReadOnlySet<T>`|セットの読み取り専用の抽象化を提供します。|

### 要素の比較をサポートするクラス

要素の比較をサポートする`IComparer<T>`、`IEqualityComparer<T>`を実装する基本クラスが定義されています。

|クラス|説明|
|--|--|--|
|`Comparer<T>`|`IComparer<T>` ジェネリック インターフェイスの実装のための基本クラスを提供します。|
|`ReferenceEqualityComparer`|2 つのオブジェクト インスタンスを比較するときに、値の等価性 (`Equals(Object)`) ではなく参照の等価性 (`ReferenceEquals(Object, Object)`) を使用する `IEqualityComparer<T>`。|
|`EqualityComparer<T>`|`IEqualityComparer<T>` ジェネリック インターフェイスの実装のための基本クラスを提供します。|

### コレクションクラス

基本的なコレクションのクラスが定義されています。

|クラス|説明|
|--|--|--|
|`Dictionary<TKey,TValue>`|キーと値のコレクションを表します。|
|`HashSet<T>`|値のセットを表します。|
|`LinkedList<T>`|ダブルリンク リストを表します。|
|`List<T>`|インデックスを使用してアクセスできる、厳密に型指定されたオブジェクトのリストを表します。 リストの検索、並べ替え、および操作のためのメソッドを提供します。|
|`Queue<T>`|オブジェクトの先入れ先出しコレクションを表します。|
|`Stack<T>`|指定した同じ型のインスタンスの、後入れ先出し (LIFO) の可変サイズのコレクションを表しま|
|`SortedDictionary<TKey,TValue>`|キーに基づいて並べ替えられた、キーと値のペアのコレクションを表します。|
|`SortedList<TKey,TValue>`|関連付けられた `IComparer<T>` 実装に基づいて、キーにより並べ替えられた、キーと値のペアのコレクションを表します。|
|`SortedSet<T>`|一定の並べ替え順序で管理されたオブジェクトのコレクションを表します。|


## `System.Collections.ObjectModel` 名前空間
>Microsoft Docs: https://docs.microsoft.com/ja-jp/dotnet/api/system.collections.objectmodel?view=net-5.0
>再利用可能なライブラリのオブジェクト モデル内のコレクションとして使用できるクラスが含まれています。 
これらのクラスは、プロパティまたはメソッドがコレクションを返す場合に使用します。

コレクションクラスの基本クラスや、読み取り専用コレクションのクラスが定義されています。
プロパティやメソッドなどでコレクションを外部に公開する際にこれらのクラスを利用します。

### クラス

|クラス|説明|
|--|--|
|`Collection<T>`|ジェネリック コレクションの基本クラスを提供します。|
|`KeyedCollection<TKey,TItem>`|キーが値に埋め込まれているコレクションの抽象基本クラスを提供します。|
|`ObservableCollection<T>`|項目が追加または削除されたとき、あるいはリスト全体が更新されたときに通知を行う動的なデータ コレクションを表します。|
|`ReadOnlyCollection<T>`|読み取り専用のジェネリック コレクションの基本クラスです。|
|`ReadOnlyDictionary<TKey,TValue>`|キーと値のペアの読み取り専用ジェネリック コレクションを表します。|
|`ReadOnlyObservableCollection<T>`|読み取り専用の `ObservableCollection<T>` を表します。|

## `System.Collections.Concurrent` 名前空間
>Microsoft Docs: https://docs.microsoft.com/ja-jp/dotnet/api/system.collections.concurrent?view=net-5.0
スレッド セーフなコレクション クラスがいくつか用意されています。複数のスレッドがコレクションに同時にアクセスするときは必ず、これらのコレクション クラスを System.Collections 名前空間および System.Collections.Generic 名前空間の対応する型の代わりに使用する必要があります。 
ただし、拡張メソッドや明示的なインターフェイスの実装を介したコレクション オブジェクトの要素へのアクセスは、スレッドセーフであるという保証はなく、呼び出し元による同期が必要になる場合があります。

複数スレッドから同時にアクセス可能なコレクションが定義されています。
Producer-Consumer パターンの実装をサポートする`BlockngCollection<T>` や、タスク並列処理に用いられる`Partitoner<T>`などがあります。

- [.NET での並列プログラミング | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/standard/parallel-programming/)
- [BlockingCollection<T> クラス | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/api/system.collections.concurrent.blockingcollection-1?view=net-5.0)

### クラス

|クラス|説明|
|--|--|
|`BlockingCollection<T>`|`IProducerConsumerCollection<T>` を実装するスレッド セーフなコレクションに、ブロッキングと範囲指定の機能を提供します。|
|`ConcurrentBag<T>`|オブジェクトの順序付けられていないスレッド セーフなコレクションを表します。|
|`ConcurrentDictionary<TKey,TValue>`|同時に複数のスレッドからアクセスできる、スレッド セーフなキーと値のペアのコレクションを表します。|
|`ConcurrentQueue<T>`|スレッド セーフな先入れ先出し (FIFO) コレクションを表します。|
|`ConcurrentStack<T>`|スレッド セーフな後入れ先出し (LIFO) コレクションを表します。|
|`OrderablePartitioner<TSource>`|並べ替え可能なデータ ソースを複数のパーティションに分割する特定の方法を表します。|
|`Partitioner`|配列、リスト、および列挙体に使用できる共通のパーティション方法を提供します。|
|`Partitioner<TSource>`|データ ソースを複数のパーティションに分割する特定の方法を表します。|

### インターフェース

|インターフェイス|説明|
|--|--|
|IProducerConsumerCollection<T>|プロデューサーまたはコンシューマーが使用するためのスレッド セーフなコレクションを操作するメソッドを定義します。 このインスタンスには、プロデューサー/コンシューマー コレクションの統一された表現が用意されています。BlockingCollection<T> のような高度な抽象化では、基になるストレージ機構としてこのコレクションを使用できます。|


## `System.Collections.Immutable` 名前空間
>Microsoft Docs: https://docs.microsoft.com/ja-jp/dotnet/api/system.collections.immutable?view=net-5.0
変更できないコレクションを定義するインターフェイスとクラスが含まれます。


> 変更できないコレクションを使用すると、以下のことができます。
・ コレクションが変更されないことをコンシューマーが確実に保証できるように、コレクションを共有します。
・ マルチスレッド アプリケーションで暗黙的なスレッド セーフを提供します (コレクションにアクセスするためにロックは不要)。
・ 関数型プログラミングの方法に従います。
・ 元のコレクションを維持しながら、列挙中にコレクションを変更します。

### インターフェイス

|インターフェイス|説明|
|--|--|
|`IImmutableDictionary<TKey,TValue>`|キーと値のペアの変更できないコレクションを表します。|
|`IImmutableList<T>`|変更できない要素のリストを表します。|
|`IImmutableQueue<T>`|オブジェクトの変更できない先入れ先出しコレクションを表します。|
|`IImmutableSet<T>`|セットの新しいインスタンスを作成することによってのみ変更可能な要素のセットを表します。|
|`IImmutableStack<T>`|変更できない後入れ先出し (LIFO) コレクションを表します。|

### クラス

|クラス|説明|
|--|--|
|`ImmutableArray`|変更できない配列を作成するためのメソッドを提供します。つまり、この配列は、作成後に変更することができません。|
|`ImmutableArray<T>`<br>`.Builder`|余分なメモリを割り当てずに `ImmutableArray<T>` インスタンスに変換できる書き込み可能な配列アクセサー。|
|`ImmutableDictionary`|`ImmutableDictionary<TKey,TValue>` クラスのインスタンスの一連の初期化メソッドを提供します。|
|`ImmutableDictionary<TKey,TValue>`<br>`.Builder`|メモリ割り当てがほとんどまたはまったくない場合でも変化し、変更できないハッシュ マップのインスタンス上で非常に効率よく生成またはビルドできるハッシュ マップを表します。|
|`ImmutableDictionary<TKey,TValue>`|変更できない、順序指定されていないキーと値のコレクションを表します。|
|`ImmutableHashSet`|`ImmutableHashSet<T>` クラスのインスタンスの一連の初期化メソッドを提供します。|
|`ImmutableHashSet<T>.Builder`|メモリ割り当てがほとんどまたはまったくない場合でも変化し、変更できないハッシュ セットのインスタンス上で非常に効率よく生成またはビルドできるハッシュ セットを表します。|
|`ImmutableHashSet<T>`|変更できない、順序が指定されていないハッシュ セットを表します。|
|`ImmutableInterlocked`|変更できないコレクションのインタロック交換メカニズムが含まれています。|
|`ImmutableList`|`ImmutableList<T>` クラスのインスタンスの一連の初期化メソッドを提供します。|
|`ImmutableList<T>`<br>`.Builder`|メモリ割り当てがほとんどまたはまったくない場合でも変化し、変更できないリストのインスタンス上で非常に効率よく生成またはビルドできるリストを表します。|
|`ImmutableList<T>`|変更できないリスト (インデックスを使用してアクセスできる、厳密に型指定されたオブジェクトのリスト) を表します。|
|`ImmutableQueue`|`ImmutableQueue<T>` クラスのインスタンスの一連の初期化メソッドを提供します。|
|`ImmutableQueue<T>`|変更できないキューを表します。|
|`ImmutableSortedDictionary`|`ImmutableSortedDictionary<TKey,TValue>` クラスのインスタンスの一連の初期化メソッドを提供します。|
|`ImmutableSortedDictionary<TKey,TValue>`<br>`.Builder`|メモリ割り当てがほとんどまたはまったくない場合でも変化し、変更できない並べ替えられたディクショナリのインスタンス上で非常に効率よく生成またはビルドできる、並べ替えられたディクショナリを表します。|
|`ImmutableSortedDictionary<TKey,TValue>`|変更できない並べ替えられたディクショナリを表します。|
|`ImmutableSortedSet`|`ImmutableSortedSet<T>` クラスのインスタンスの一連の初期化メソッドを提供します。|
|`ImmutableSortedSet<T>`<br>`.Builder`|メモリの割り当てをほとんどまたはまったく伴わずに変更が可能な並べ替えられたセットを表し、変更できない並べ替えられたセットを効率的に操作または構築します。|
|`ImmutableSortedSet<T>`|変更できない並べ替えられたセットの実装を表します。|
|`ImmutableStack`|`ImmutableStack<T>` クラスのインスタンスの一連の初期化メソッドを提供します。|
|`ImmutableStack<T>`|変更できないスタックを表します。|


# .NET（C#）のコレクションに関連する公式ドキュメント

Microsoftの公式ドキュメントには、コレクションに関する様々な情報が記載されています。
特定のトピックについて詳しく踏み込んだ情報なども記載されていますので、一度確認してみることをお勧めします。

## [コレクション (C#) | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/concepts/collections)

コレクションの種類、基本的な使い方など概要的な情報が確認できます。

- 単純なコレクションを使用する
- コレクションの種類
    - System.Collections.Generic のクラス
    - System.Collections.Concurrent のクラス
    - System.Collections のクラス
- キーと値のペアのコレクションを実装する
- LINQ を使用してコレクションにアクセスする
- コレクションを並べ替える
- カスタム コレクションを定義する
- 反復子

## [コレクションとデータ構造 | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/standard/collections/)

適切なコレクションを選択するための情報など、.NETで用意されているコレクションに関する様々なトピックが記載されています。

- [コレクションクラスの選択](https://docs.microsoft.com/ja-jp/dotnet/standard/collections/selecting-a-collection-class)
- [一般的に使用されるコレクション型](https://docs.microsoft.com/ja-jp/dotnet/standard/collections/commonly-used-collection-types)
- [ジェネリック コレクションを使用する状況](https://docs.microsoft.com/ja-jp/dotnet/standard/collections/when-to-use-generic-collections)
- [コレクション内での比較と並べ替え](https://docs.microsoft.com/ja-jp/dotnet/standard/collections/comparisons-and-sorts-within-collections)
- [Sorted コレクション型](https://docs.microsoft.com/ja-jp/dotnet/standard/collections/sorted-collection-types)
- [Hashtable コレクション型と Dictionary コレクション型](https://docs.microsoft.com/ja-jp/dotnet/standard/collections/hashtable-and-dictionary-collection-types)
- [スレッド セーフなコレクション](https://docs.microsoft.com/ja-jp/dotnet/standard/collections/thread-safe/)