今回は、C#のDictionaryクラスの使い方についてご紹介します。
Dictionaryとは
C#のDictionary<TKey, TValue>クラスは、キーと値のペアを効率よく管理するためのジェネリックコレクションです。
内部的にはハッシュテーブルを用いているため、要素の追加・更新・検索などを高速に処理できる特徴があります。
キーの重複は許されず、同一のキーで再度データを追加すると例外が発生する点に注意が必要です。
また、スレッドセーフではないため、複数スレッドから同時にアクセスする場合はConcurrentDictionaryなどの別のコレクションの検討をおすすめします。
基本的な使い方
宣言と初期化
まず、System.Collections.Generic名前空間をインポートし、Dictionaryを生成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
using System; using System.Collections.Generic; class Program { static void Main() { // 空のDictionaryを宣言 Dictionary<string, int> ages = new Dictionary<string, int>(); // 初期値を設定して宣言 Dictionary<string, int> scores = new Dictionary<string, int> { { "Alice", 85 }, { "Bob", 92 } }; // Aliceのスコアを取得して表示 Console.WriteLine(scores["Alice"]); } } |
85
上記のように初期化時に要素をまとめて設定することもできます。
キーと値の型を自由に指定できるため、様々なデータに応用が可能です。
要素の追加と更新
要素の追加にはAddメソッドかインデクサーを使用します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
using System; using System.Collections.Generic; class Program { static void Main() { // Dictionaryを準備 Dictionary<string, int> ages = new Dictionary<string, int>(); // Addメソッドで追加(同じキーが存在すると例外が発生) ages.Add("Charlie", 30); // インデクサーで追加(既存のキーなら上書きされる) ages["Diana"] = 28; // Charlieの年齢を更新(既に存在するため上書き) ages["Charlie"] = 31; // 追加・更新したデータを表示 Console.WriteLine($"Charlie: {ages["Charlie"]}"); Console.WriteLine($"Diana: {ages["Diana"]}"); } } |
Charlie: 31
Diana: 28
Addを使う場合は重複キーに注意し、既存キーがあるかどうか確認したい場合はContainsKeyやTryGetValueの利用を検討します。
要素の取得と存在確認
存在しないキーをインデクサーで参照すると例外が発生するため、ContainsKeyやTryGetValueで安全にチェックできます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
using System; using System.Collections.Generic; class Program { static void Main() { Dictionary<string, int> scores = new Dictionary<string, int> { { "Alice", 85 }, { "Bob", 92 } }; // インデクサーで取得(キーがないと例外が発生するので注意) int aliceScore = scores["Alice"]; Console.WriteLine($"Aliceのスコア: {aliceScore}"); // TryGetValueで安全に取得 if (scores.TryGetValue("Bob", out int bobScore)) { Console.WriteLine($"Bobのスコア: {bobScore}"); } else { Console.WriteLine("Bobというキーは存在しません。"); } // 存在確認のみ行いたい場合 if (!scores.ContainsKey("Eve")) { Console.WriteLine("Eveのスコアは登録されていません。"); } } } |
Aliceのスコア: 85
Bobのスコア: 92
Eveのスコアは登録されていません。
TryGetValueは、キーの存在チェックと値取得を同時に行えるため便利です。
要素の削除と全削除
Removeメソッドで特定のキーを削除し、Clearメソッドで全要素を削除できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
using System; using System.Collections.Generic; class Program { static void Main() { Dictionary<string, int> scores = new Dictionary<string, int> { { "Alice", 85 }, { "Bob", 92 } }; // 指定のキーを削除 bool removed = scores.Remove("Alice"); Console.WriteLine($"Aliceを削除した: {removed}"); // 全削除 scores.Clear(); Console.WriteLine($"Dictionaryの要素数: {scores.Count}"); } } |
Aliceを削除した: True
Dictionaryの要素数: 0
キーが見つからない場合はfalseが返されるため、削除可否を判定できます。
実用的な具体例
ここでは、複数のキーと値を扱いながら走査(ループ)や追加・更新を同時に行う例を示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
using System; using System.Collections.Generic; class Program { static void Main() { // Dictionaryの宣言と初期化 Dictionary<string, int> inventory = new Dictionary<string, int> { { "Potion", 10 }, { "Hi-Potion", 5 }, { "Antidote", 2 } }; // 要素を走査して在庫を表示 Console.WriteLine("在庫一覧:"); foreach (KeyValuePair<string, int> item in inventory) { Console.WriteLine($"{item.Key}: {item.Value}個"); } // 新たなアイテムを追加 inventory["Elixir"] = 1; // 既存アイテム(Potion)の数を更新 if (inventory.ContainsKey("Potion")) { inventory["Potion"] += 5; // 5個追加 } // 更新後の一覧を表示 Console.WriteLine("\n更新後の在庫一覧:"); foreach (string key in inventory.Keys) { Console.WriteLine($"{key}: {inventory[key]}個"); } } } |
在庫一覧:
Potion: 10個
Hi-Potion: 5個
Antidote: 2個
更新後の在庫一覧:
Potion: 15個
Hi-Potion: 5個
Antidote: 2個
Elixir: 1個
このように、Dictionaryを活用することで大量のデータをキーと値で素早く管理できます。
注意点
キーの一意性が要求されるため、同じキーでAddを呼び出すと例外が発生します。
また、nullキーは通常許可されないので注意が必要です。
スレッドセーフではないため、マルチスレッド環境での利用はロック機構の導入かConcurrentDictionaryの活用が推奨されます。
さらに、大量のデータを取り扱う場合は初期容量を指定すると再ハッシュの回数が減り、パフォーマンス向上に役立ちます。
まとめ
C#のDictionaryクラスは、キーと値を効率的に管理できる強力なコレクションです。
要素の追加・更新・削除・走査などの操作を簡単に行える点が大きなメリットです。
適切な使い方と注意点を押さえることで、より柔軟で安全なプログラムを実装できます。