System.Collections.Specialized.HybridDictionary は、要素数が少ないうちは ListDictionary、増えたら Hashtable に内部実装を切り替える ハイブリッド型の連想配列です。「要素数の見積りが付きにくい」「ほとんどの場合は数件しか入らないが、たまに大量に増える」といった用途を想定して .NET Framework 1.1 で追加されました。
HybridDictionary とは
- 名前空間:
System.Collections.Specialized - 内部構造:要素数 ≤ 8 までは ListDictionary、9 以上になると Hashtable に切り替わる
- キーは
null不可、値はnull可 - キーの比較は既定で
Equals/GetHashCode、コンストラクタで大文字小文字を無視するか選べる
using System.Collections.Specialized;
var dict = new HybridDictionary();
dict["apple"] = 150;
dict["orange"] = 120;
// 要素数が増えると内部で Hashtable に切り替わる(ユーザーからは見えない)
for (int i = 0; i < 100; i++) dict[$"key{i}"] = i;
切り替え動作はクラス内部に閉じており、利用側は 常に同じ API(IDictionary)を通して使う だけで OK です。
サポートするインターフェース
| インターフェース | 役割 |
|---|---|
IDictionary |
キー・値の組を扱う連想コレクション |
ICollection |
Count / CopyTo / 同期サポート |
IEnumerable |
foreach で DictionaryEntry を列挙 |
ICloneable は実装しません。
各インターフェースの詳細は次を参照してください。
IDictionary: Hashtable の記事ICollection: ArrayList の記事IEnumerable/IEnumerator: IEnumerable と IEnumerator の記事
切り替えの仕組み
HybridDictionary は最初は内部に ListDictionary(線形探索の単方向リスト)を持ちます。要素数が一定の閾値(実装上は約 8 件)を超えると Hashtable を生成して中身を移し替え、以降は Hashtable で動作します。逆方向(Hashtable → ListDictionary)への戻しは行われません。
var d = new HybridDictionary(initialSize: 16); // 初期容量
// initialSize が大きいと最初から Hashtable で動く実装もあるため
// 実際の挙動は .NET 実装によって若干異なる
要素が少ないあいだは Hashtable のハッシュ計算より単純な線形探索のほうが速い という前提で設計されています。
主な API と計算量
| 操作 | 要素数少 | 要素数多 |
|---|---|---|
| 取得 | O(n)(線形探索) | O(1)(ハッシュ) |
| 追加 | O(n) | O(1) 償却 |
| 削除 | O(n) | O(1) |
| 列挙 | O(n) | O(n) |
少要素では n が小さいので O(n) でも実時間は Hashtable より速い、という想定。閾値前後で挙動特性が変わる点を理解しておきましょう。
ボックス化と型安全
HybridDictionary は非ジェネリックなのでキー・値ともに object。値型はボックス化されます。新規コードでは Dictionary<TKey, TValue> を使うのが標準です。
Dictionary<TKey, TValue> との比較
| 観点 | HybridDictionary |
Dictionary<TKey, TValue> |
|---|---|---|
| 型安全 | × object |
◯ |
| 値型のボックス化 | 発生 | 発生しない |
| 小規模時の最適化 | ◯ 線形探索 | × 常にハッシュ |
| 推奨度 | レガシーのみ | 新規コードの標準 |
実際のところ、Dictionary<TKey, TValue> のハッシュ計算オーバーヘッドは小規模でも十分軽く、わざわざ HybridDictionary を選ぶ性能上の利点はほぼありません。
使いどころ
- レガシーコードのメンテナンス:.NET Framework 1.x 時代の API が
HybridDictionaryを返してくる場合。 - 学習目的:要素数によって内部実装を切り替える設計パターンの実例として。
新規コードで採用する積極的な理由は基本的にありません。型安全 + 値型対応 + 性能の三拍子が揃った Dictionary<TKey, TValue> を選ぶか、要素が極端に少ないことが分かっているなら配列やタプルで済ませるのが現代的です。
注意点
- キーは
null不可:Hashtable由来の制約。 - キー比較:コンストラクタ
HybridDictionary(bool caseInsensitive)で大文字小文字を無視できるが、対象は文字列キーのみ。任意のIEqualityComparerを渡す API はない。 - スレッドセーフでない:並行アクセスには別途ロックが必要。
まとめ
HybridDictionaryは 小規模でListDictionary、大規模でHashtableに切り替わる ハイブリッド辞書。IDictionary/ICollection/IEnumerableを実装。- 切り替え閾値は 8 件付近。要素数が少ない用途を想定したレガシークラス。
- 新規コードでは
Dictionary<TKey, TValue>一択。HybridDictionaryはレガシー API 互換のためだけに存在する。