データをグループ化して一つのオブジェクトとして扱う方法、幾つかあるらしい。
それは知っているが、結局ちゃんとわかっていないから適当に配列に突っ込んンで何とかしようとするのもうやめよう。
愚者を救うべく、我々は調査に赴いた。
目次
1. コレクションとは何か?
1.1 System.Collections.Generic
1.2 System.Collections.Concurrent
1.3 System.Collection
1.4 System.Linq
1.5 System.Collection.ObjectModel
1.6 名前空間ではないが、ReactivePropertyのコレクション
2. コレクションの目的
3. 何がいいのか?
4. 悪い(気を付ける)ことは?
5. いつ使えば良いのか
6. まとめ
7. 参照
1. コレクションとは何か?
- 以下で示す名前空間(`System.Collection~)。
- 広義にはコレクション自体はデータをグループ化されたオブジェクトの総称。
- 狭義にはIEnumerableを継承したクラスのこと。
- 又、ICollectionインターフェイスを継承したクラスやインターフェイスを指す。
冒頭で配列とコレクションは別物かのように書きましたが、配列もSystem.Collection.ICollection
の実装です。
又、後述のArrayListやListも配列と呼ぶことがあるようです。
++C++//未確認飛行c-配列リスト
狭義にはSystem.Array
クラスのことを指します。
以下に各名前空間を継承したクラス・インターフェイスの一部を記す。
1.1System.Collections.Generic
ジェネリックなコレクションを生成できる。つまり要素が一つのデータ型の場合使う。
-
IEnumerable<T>
-
ICollection<T>
-
IDictionary<TKey,TValue>
: KeyとValueのコレクション。Keyによるアクセスなので高速。 -
IList<T>
: Dictionaryと比較し、添字(インデックス)を使った操作が強味。Listではインデックスを利用した検索・並び替え ・操作ができる。 -
IReadOnlyCollection<T>
:IEnumerable+Countプロパティというコンパクト。別System.Collections.ObjectModel.ReadOnlyCollection<T>
とは無縁。 ISet<T>
-
-
1.2System.Collections.Concurrent
複数のスレッドからアクセスする場合。効率的なスレッドセーフ操作が可能。
(スレッドセーフとは:「そのコードを複数のスレッドが同時並行的に実行しても問題が発生しないこと」Wikipedia-スレッドセーフ)
1.3System.Collection
要素はObject型として保存される。レガシーなので可能な限りCollection.GenericかCollectionConcurrentを使う。
-
BitArray
クラス:Bool型で数値を管理する。 -
ArrayList
クラス:サイズ可変のListとして使える。
1.4System.Collection.ObjectModel
-
ObservableCollection<T>
:変更通知イベントを発生させられる。IObservableやIObserverとは関係ない。 -
ReadOnlyCollection<T>
:紛らわしいがIReadOnlyList<T>
、IList<T>
の実装クラス。IListをラッピングして書き換え不可で公開できる。 ReadOnlyDictionary<T>
ReadOnlyObservable<T>
1.5System.Linq
クエリ発行のために用いる。
-
ILookup
:Key:Value
= 1:Nとすることができる。Dictionary<>のElementをList<>にするような無様なことをしなくて済む。 IGrouping
IQuaryable
以下のリンクがTips的によくまとめられておりました。勉強になりました。
意外と知らない!? C#の便利なコレクション!
あまり見かけないけど便利な LINQ メソッド を使いこなす!
1.6名前空間ではないが、ReactivePropertyのコレクションも同様に記す。
- ReactiveCollectionクラス
- ReadOnlyReactiveCollectionクラス:ObservableCollectionを監視して、元のコレクションを加工する。
- IFilteredReadOnlyObservableCollectionインターフェイス
MVVMをリアクティブプログラミングで快適にReactivePropertyオーバービュー
github-ReactiveProperty
2. 目的
- 関連するオブジェクトをグループにしてまとめる。
3. 何がいいのか?
配列の場合、数が固定されていたり、型を指定したりなど縛りが強い。
コレクションだと配列よりも柔軟に処理ができる。
4. 悪い(気を付ける)ことは?
- コレクション自体を変更できるという性質が、コードを分かりづらくすることがある。
引数をReadOnlyなものにするなど、メソッドシグネチャ(引数と戻り値)だけでメソッドの振る舞いを分かるようにするのがベスト。
対策として、IListの代わりにIEnumerable型を使うなどがある。
IEnumerable型は繰り返しの為の型なので、Listの用に中身をAddしたりRemoveしたりはされないと推測できる。分かりやすくなる。
引数の型を何でも List にしちゃう奴にそろそろ一言いっておくか
5. いつ使えばいいのか?
データをグループ化したい時の考え方
何の為にグループ化するのか。
イテレーション? => IEnumerable
並び替え? => List
高速索引? => Dictionary
重複削除や演算? => HashSet
C#(.NET)コレクションの使い分けヒント
コレクションとデータ構造体
6. まとめ
コレクションのできること
- 列挙
- 内容を配列にコピー
- 要素数・要素の処理
- 複数スレッドからのアクセス同期
コレクション…というよりIEnumerableを継承したクラス・I/Fは
類似した名称でありながら、名前空間すら違うという紛らわしい世界を形成している。
用途・メンテナンス性を考慮して選ばなければならない。
IEnumerableをLinqで廻した後にToListやToArrayでリストや配列にしているのをよく見るが
その後データを追加・削除するならリスト、しないなら配列に変換する。
端からIReadOnlyListかIReadOnlyCollectionにしてもいい。
======================================================================================================
コレクションという漠然としたテーマで調べたがひとえに説明できないほど風呂敷が広がってしまった。
調べきれなかったことも多大にあるが今回はこれにとどめておく。
System.Collections.Concurrent
の辺りは追々追記したい。という気持ちはある。気持ちは。
======================================================================================================
7. 参照
コレクション (C#)
System.Linq
System.Collection.ObjectModel
System.Collection
System.Collections.Concurrent
System.Collections.Generic
System.Collections.Generic
引数の型を何でも List にしちゃう奴にそろそろ一言いっておくか
MVVMをリアクティブプログラミングで快適にReactivePropertyオーバービュー
github-ReactiveProperty
意外と知らない!? C#の便利なコレクション!
あまり見かけないけど便利な LINQ メソッド を使いこなす!
コレクションとデータ構造体