Dictionary<TKey, TValue> とは
C#においてDictionary<TKey, TValue>は、**キー(Key)と値(Value)**のペアをセットで格納するコレクションです。
List<T>がインデックス(0, 1, 2...)で要素を管理するのに対し、Dictionaryは"ProductID-001"や"UserName"のような、より意味のある「キー」を使って、関連する「値」にアクセスします。
- キー(Key): データを一意に識別するためのもの(例: 社員ID)。辞書内で重複することはできません。
- 値(Value): キーに関連付けられたデータ(例: 社員名)。
この構造により、Dictionaryは特定のキーに基づいたデータの**高速な検索(ルックアップ)**を最も得意とします。
Dictionaryを使用するには、System.Collections.Generic名前空間をusingする必要があります。
1. Dictionary の初期化
Dictionaryは、宣言と同時に初期化できます。ここでは、string型のキー(商品SKU)とstring型の値(商品名)を格納する辞書を作成します。
C# 6.0以降のインデクサ構文(["キー"] = 値)を使用すると、初期化が簡潔に記述できます。
using System;
using System.Collections.Generic;
public class DictionaryInitializationExample
{
public static void Main()
{
// 宣言と同時に、コレクション初期化子({})と
// インデクサ構文([] =)で値を設定
var productCatalog = new Dictionary<string, string>
{
["SKU-A100"] = "Premium Monitor",
["SKU-B205"] = "Wireless Keyboard",
["SKU-C310"] = "Optical Mouse"
};
Console.WriteLine($"初期化時の要素数: {productCatalog.Count}");
}
}
2. 要素の追加と更新
Dictionaryへの要素の追加・更新は、主に2つの方法で行います。
インデクサ ["key"] (追加または更新)
配列やList<T>と同じようにインデクサ([])を使用します。
- キーが存在しない場合は、新しい要素として追加されます。
- キーが既に存在する場合は、そのキーの値が**上書き(更新)**されます。
// "SKU-D400" は存在しないため、新しい要素として追加される
productCatalog["SKU-D400"] = "USB Hub";
// "SKU-C310" は既に存在するため、値が上書き(更新)される
productCatalog["SKU-C310"] = "Gaming Mouse (Upgraded)";
TryAdd メソッド (安全な追加)
もしキーが既に存在する場合に上書きしたくない場合は、TryAddメソッドを使用します。TryAddは、キーが存在しなかった場合にのみ追加を行い、成功したか(true)失敗したか(false)をbool値で返します。
// "SKU-E500" は存在しないため、追加に成功する
bool addedNew = productCatalog.TryAdd("SKU-E500", "Webcam");
// addedNew は true
// "SKU-A100" は既に存在するため、追加は失敗し、上書きもされない
bool addedExisting = productCatalog.TryAdd("SKU-A100", "Standard Monitor");
// addedExisting は false
3. 要素の取得(読み取り)
Dictionaryから値を取得する方法にも、安全な方法と、注意が必要な方法があります。
インデクサ ["key"] (高速だが危険な場合も)
インデクサ([])でキーを指定すると、対応する値が瞬時に返されます。 ただし、もし指定したキーがDictionary内に存在しなかった場合、KeyNotFoundExceptionという実行時エラーが発生し、プログラムが停止します。
// 存在するキーを指定
string monitorName = productCatalog["SKU-A100"];
Console.WriteLine($"SKU-A100 の名前: {monitorName}");
// 存在しないキーを指定
// string notFound = productCatalog["SKU-999"]; // KeyNotFoundException が発生
ContainsKey メソッド (安全な確認)
KeyNotFoundExceptionを避けるため、ContainsKeyメソッドでキーの存在を事前に確認してから、インデクサでアクセスするのが安全な方法の一つです。
string keyToFind = "SKU-B205";
if (productCatalog.ContainsKey(keyToFind))
{
// キーの存在が保証されているため、安全にアクセスできる
string keyboardName = productCatalog[keyToFind];
Console.WriteLine($"'{keyToFind}' の名前: {keyboardName}");
}
TryGetValue メソッド (推奨される安全な取得)
ContainsKeyとインデクサ[]を組み合わせると、Dictionaryへの検索(ルックアップ)が2回発生します。
TryGetValueメソッドは、この「確認」と「取得」を一度の操作で、より効率的に行います。
- キーが存在した場合:
trueを返し、out引数で指定した変数に値を格納します。 - キーが存在しない場合:
falseを返し、例外はスローしません。
// "SKU-C310" (Gaming Mouse) を検索
if (productCatalog.TryGetValue("SKU-C310", out string mouseName))
{
// 成功
Console.WriteLine($"TryGetValue 成功: {mouseName}");
}
// "SKU-999" を検索
if (!productCatalog.TryGetValue("SKU-999", out string notFoundName))
{
// 失敗
Console.WriteLine($"TryGetValue 失敗: SKU-999 は見つかりませんでした。");
}
4. foreach による反復処理
foreachループを使用して、Dictionaryに含まれるすべての要素(キーと値のペア)を処理できます。
foreachで取り出される item は、KeyValuePair<TKey, TValue> という型のオブジェクトであり、item.Keyプロパティでキーを、item.Valueプロパティで値を取得できます。
Console.WriteLine("\n--- カタログ全商品一覧 ---");
// 'pair' は KeyValuePair<string, string> 型
foreach (var pair in productCatalog)
{
Console.WriteLine($"SKU: {pair.Key} = 商品名: {pair.Value}");
}
出力結果(Dictionaryは順序を保証しません):
--- カタログ全商品一覧 ---
SKU: SKU-A100 = 商品名: Premium Blue Widget
SKU: SKU-B205 = 商品名: Wireless Keyboard
SKU: SKU-C310 = 商品名: Gaming Mouse (Upgraded)
SKU: SKU-D400 = 商品名: USB Hub
SKU: SKU-E500 = 商品名: Webcam
C#コード全体
using System;
using System.Collections.Generic;
public class DictionaryUsageExample
{
public static void Main()
{
// 1. Dictionary の初期化 (C# 6.0 インデクサ構文)
var productCatalog = new Dictionary<string, string>
{
["SKU-A100"] = "Premium Monitor",
["SKU-B205"] = "Wireless Keyboard",
["SKU-C310"] = "Optical Mouse"
};
Console.WriteLine($"初期化時の要素数: {productCatalog.Count}");
// 2. 要素の追加と更新 (インデクサ)
productCatalog["SKU-D400"] = "USB Hub"; // 追加
productCatalog["SKU-C310"] = "Gaming Mouse (Upgraded)"; // 更新
// 3. TryAdd による安全な追加
bool addedNew = productCatalog.TryAdd("SKU-E500", "Webcam");
bool addedExisting = productCatalog.TryAdd("SKU-B205", "Mechanical Keyboard");
Console.WriteLine($"新規追加 (TryAdd): {addedNew} (True)");
Console.WriteLine($"既存追加 (TryAdd): {addedExisting} (False)");
// 4. 要素の取得 (TryGetValue)
if (productCatalog.TryGetValue("SKU-C310", out string mouseName))
{
Console.WriteLine($"TryGetValue 成功: {mouseName}");
}
if (!productCatalog.TryGetValue("SKU-999", out string notFoundName))
{
Console.WriteLine($"TryGetValue 失敗: SKU-999 は見つかりませんでした。");
}
// 5. foreach による反復処理
Console.WriteLine("\n--- カタログ全商品一覧 ---");
foreach (var pair in productCatalog)
{
Console.WriteLine($"SKU: {pair.Key} = 商品名: {pair.Value}");
}
}
}
まとめ
Dictionary<TKey, TValue>は、C#でキーと値のペアを管理するための非常に強力で高速なコレクションです。
- 追加・更新:
myDict["key"] = value(上書き)またはmyDict.TryAdd("key", value)(上書きしない)。 - 安全な取得:
if (myDict.TryGetValue("key", out var value))を使用するのが標準的な方法です。 - 反復処理:
foreach (var pair in myDict)でpair.Keyとpair.Valueを使用します。
