C# Dictionaryの使い方を初心者向けに徹底解説|追加・取得・削除・ループ処理までわかる入門ガイド

はじめに

C#で複数のデータを扱うときは、配列やListがよく使われます。しかし、「名前を指定して年齢を取得する」「商品コードから商品情報を探す」といった処理では、Dictionaryを使うとコードをシンプルに書けます。

Dictionaryでは、データを識別するための「キー」と、実際に保存したい「値」を組み合わせて管理します。たとえば、社員番号をキー、社員名を値として登録すれば、社員番号を指定するだけで対応する社員名を取得できます。

この記事では、C#のDictionaryについて、次の内容を初心者向けに解説します。

  • Dictionaryの基本的な仕組み

  • 配列やListとの違い

  • 宣言、作成、初期化の方法

  • 要素を追加する方法

  • キーが重複した場合の動作

サンプルコードを確認しながら、C#におけるDictionaryの基本的な使い方を身につけていきましょう。

1. C#のDictionaryとは?初心者向けに基本を解説

C#のDictionary<TKey, TValue>は、キーと値の組み合わせを複数保存できるコレクションです。

TKeyにはキーのデータ型、TValueには値のデータ型を指定します。たとえば、キーを文字列、値を整数として扱う場合は、次のように記述します。

Dictionary<string, int>

この場合、次のようなデータを管理できます。

キー
"田中"25
"佐藤"32
"鈴木"28

キーを指定して対応する値を扱えることが、Dictionaryの大きな特徴です。

1-1. Dictionaryはキーと値をセットで管理するコレクション

Dictionaryでは、1つの要素が「キー」と「値」のペアで構成されます。

たとえば、商品の情報を次のように管理するとします。

Dictionary<string, string> products = new Dictionary<string, string>();

products.Add("A001", "ノートパソコン");products.Add("A002", "ワイヤレスマウス");products.Add("A003", "キーボード");

このコードでは、商品コードがキー、商品名が値です。

キー「A001」 → 値「ノートパソコン」キー「A002」 → 値「ワイヤレスマウス」キー「A003」 → 値「キーボード」

登録した値は、キーを指定して取得できます。

Console.WriteLine(products["A002"]);

実行結果は次のとおりです。

ワイヤレスマウス

配列やListでは、基本的に01などのインデックスを使って要素を指定します。一方、Dictionaryでは、商品コードやユーザーIDなど、データの意味に合ったキーを使用できます。

なお、1つのDictionaryに同じキーを複数登録することはできません。キーは重複できませんが、値は重複しても問題ありません。

1-2. 配列やListとの違い

配列、ListDictionaryは、いずれも複数のデータを管理するために使われます。ただし、データの指定方法や適した用途が異なります。

主な違いは次のとおりです。

種類要素の指定方法要素数の変更適した用途
配列インデックス基本的に固定要素数が決まっているデータ
Listインデックス追加・削除が可能順番に並ぶデータ
Dictionaryキー追加・削除が可能キーと値を関連付けるデータ

配列では、作成時に要素数を指定します。

string[] fruits = new string[3];

fruits[0] = "りんご";fruits[1] = "みかん";fruits[2] = "ぶどう";

Listでは、要素を後から自由に追加できます。

List<string> fruits = new List<string>();

fruits.Add("りんご");fruits.Add("みかん");fruits.Add("ぶどう");

配列やListの要素を取得するときは、インデックスを指定します。

Console.WriteLine(fruits[1]);

一方、Dictionaryでは任意のキーを指定します。

Dictionary<string, int> prices = new Dictionary<string, int>();

prices.Add("りんご", 150);prices.Add("みかん", 120);prices.Add("ぶどう", 500);

Console.WriteLine(prices["みかん"]);

実行結果は次のとおりです。

120

List<T>は、整数のインデックスを使って要素にアクセスする、順序を持つリストとして提供されています。商品コードや名前などを手掛かりにデータを管理したい場合は、Dictionaryのほうが適しています。

1-3. Dictionaryを使うメリットと適した場面

Dictionaryを使う主なメリットは、データの意味に合ったキーを指定して値を管理できることです。

たとえば、都道府県名から県庁所在地を取得するデータを考えてみましょう。

Dictionary<string, string> capitals = new Dictionary<string, string>{{ "北海道", "札幌市" },{ "宮城県", "仙台市" },{ "東京都", "新宿区" },{ "愛知県", "名古屋市" },{ "大阪府", "大阪市" }};

東京都のデータを使用したい場合は、次のようにキーを指定できます。

Console.WriteLine(capitals["東京都"]);

実行結果は次のとおりです。

新宿区

Dictionaryは、次のような場面に適しています。

  • 商品コードと商品情報を関連付ける

  • ユーザーIDとユーザー名を関連付ける

  • 設定名と設定値を管理する

  • 単語と意味を管理する

  • 都道府県名と県庁所在地を関連付ける

  • エラーコードとエラーメッセージを管理する

  • ファイルの拡張子と処理方法を関連付ける

たとえば、HTTPのステータスコードと説明を管理する場合は、次のように記述できます。

Dictionary<int, string> statusMessages = new Dictionary<int, string>{{ 200, "成功" },{ 400, "不正なリクエスト" },{ 404, "ページが見つかりません" },{ 500, "サーバー内部エラー" }};

Console.WriteLine(statusMessages[404]);

実行結果は次のとおりです。

ページが見つかりません

このように、番号や文字列などの識別子から対応する情報を探したい場合に、Dictionaryは便利です。

ただし、要素を登録した順番に処理することが重要な場合や、同じキーを複数登録したい場合には、別のコレクションが適していることもあります。用途に応じて、配列やListなどと使い分けましょう。

1-4. Dictionaryを利用するために必要な名前空間

C#でDictionaryを使用するには、System.Collections.Generic名前空間が必要です。

通常は、ソースコードの先頭に次のusingディレクティブを記述します。

using System.Collections.Generic;

コンソールに結果を表示する場合は、System名前空間も使用します。

using System;using System.Collections.Generic;

Dictionary<string, int> scores = new Dictionary<string, int>();

scores.Add("国語", 80);scores.Add("数学", 90);

Console.WriteLine(scores["数学"]);

.NETのプロジェクト設定によっては、暗黙的なusingによって名前空間が自動的に読み込まれるため、using System.Collections.Generic;を記述しなくてもコンパイルできる場合があります。

ただし、学習中はDictionaryがどの名前空間に属しているのかを理解するためにも、必要なusingを意識しておくとよいでしょう。

usingを記述しない場合は、完全修飾名を使うこともできます。

System.Collections.Generic.Dictionary<string, int> scores =new System.Collections.Generic.Dictionary<string, int>();

この書き方でも動作しますが、コードが長くなるため、一般的にはusing System.Collections.Generic;を記述します。

2. Dictionaryの宣言・作成・初期化方法

Dictionaryを使用するには、キーと値のデータ型を指定してインスタンスを作成します。

基本構文は次のとおりです。

Dictionary<キーの型, 値の型> 変数名 =new Dictionary<キーの型, 値の型>();

キーと値には異なるデータ型を指定できます。用途に合わせて適切な型を選びましょう。

2-1. Dictionaryの基本的な宣言方法

キーを文字列、値を整数にする場合は、次のように宣言します。

Dictionary<string, int> scores = new Dictionary<string, int>();

このコードでは、次のように型を指定しています。

  • string:キーの型

  • int:値の型

  • scores:変数名

作成したDictionaryには、文字列と整数の組み合わせを登録できます。

scores.Add("国語", 80);scores.Add("数学", 95);scores.Add("英語", 88);

別のデータ型を指定することもできます。

Dictionary<int, string> users = new Dictionary<int, string>();

users.Add(1, "田中");users.Add(2, "佐藤");users.Add(3, "鈴木");

この例では、ユーザーIDを表す整数がキー、ユーザー名を表す文字列が値です。

独自クラスを値として指定することもできます。

class Product{public string Name { get; set; } = "";public int Price { get; set; }}
Dictionary<string, Product> products =new Dictionary<string, Product>();

products.Add("A001",new Product{Name = "ノートパソコン",Price = 120000});

商品コードをキーにして、複数のプロパティを持つ商品オブジェクトを管理できます。

2-2. varを使ってDictionaryを作成する方法

変数の型が右辺から明らかな場合は、varを使用できます。

var scores = new Dictionary<string, int>();

この場合、コンパイラが右辺のnew Dictionary<string, int>()から、scoresの型をDictionary<string, int>と判断します。

varを使っても、変数の型が自由に変わるわけではありません。コンパイル時に具体的な型が決まります。

そのため、次のコードは問題なく実行できます。

var scores = new Dictionary<string, int>();

scores.Add("国語", 80);scores.Add("数学", 90);

Console.WriteLine(scores["国語"]);

一方、値の型として指定したint以外のデータは追加できません。

var scores = new Dictionary<string, int>();

// コンパイルエラー// scores.Add("国語", "80点");

varを使うと型名の重複を減らせるため、コードを短くできます。

Dictionary<string, List<int>> scores =new Dictionary<string, List<int>>();

次のように書くと、より読みやすくなります。

var scores = new Dictionary<string, List<int>>();

ただし、右辺を見ても型が分かりにくい場面では、型名を明示したほうが読みやすい場合もあります。

2-3. コレクション初期化子で要素を設定する方法

Dictionaryの作成と同時に要素を登録する場合は、コレクション初期化子を使用できます。

var scores = new Dictionary<string, int>{{ "国語", 80 },{ "数学", 95 },{ "英語", 88 }};

Dictionaryを作成した後にAddメソッドを繰り返す場合と比べて、簡潔に記述できます。

次の2つのコードは、基本的に同じ内容を表しています。

var scores = new Dictionary<string, int>();

scores.Add("国語", 80);scores.Add("数学", 95);scores.Add("英語", 88);

var scores = new Dictionary<string, int>{{ "国語", 80 },{ "数学", 95 },{ "英語", 88 }};

インデクサー形式の初期化子を使用する方法もあります。

var scores = new Dictionary<string, int>{["国語"] = 80,["数学"] = 95,["英語"] = 88};

どちらの書き方でも、キーと値をまとめて初期化できます。

コレクション初期化子は、あらかじめ登録するデータが決まっている場合に便利です。曜日、設定値、ステータスコードなど、固定的なデータの定義にも向いています。

var days = new Dictionary<int, string>{{ 1, "月曜日" },{ 2, "火曜日" },{ 3, "水曜日" },{ 4, "木曜日" },{ 5, "金曜日" },{ 6, "土曜日" },{ 7, "日曜日" }};

2-4. 空のDictionaryを作成する方法

要素を登録せずにDictionaryを作成すると、空のDictionaryになります。

var users = new Dictionary<int, string>();

作成直後の要素数は0です。

Console.WriteLine(users.Count);

実行結果は次のとおりです。

0

要素は、必要になったタイミングで追加できます。

users.Add(1, "田中");users.Add(2, "佐藤");

Console.WriteLine(users.Count);

実行結果は次のとおりです。

2

アプリケーションの実行中にデータが増えていく場合は、最初に空のDictionaryを作成する方法が適しています。

たとえば、入力された単語と出現回数を管理する場合、最初からすべての単語を予測することはできません。そのため、空のDictionaryを作成し、必要に応じて要素を追加します。

var wordCounts = new Dictionary<string, int>();

Countプロパティを使えば、現在登録されている要素数を確認できます。

if (wordCounts.Count == 0){Console.WriteLine("データは登録されていません。");}

2-5. キーと値に指定できるデータ型

Dictionary<TKey, TValue>では、キーと値にさまざまなデータ型を指定できます。

文字列をキー、整数を値にする例は次のとおりです。

Dictionary<string, int> scores =new Dictionary<string, int>();

整数をキー、文字列を値にすることもできます。

Dictionary<int, string> users =new Dictionary<int, string>();

値にboolを指定する例です。

Dictionary<string, bool> settings =new Dictionary<string, bool>();

settings.Add("DarkMode", true);settings.Add("Notification", false);

値にListを指定することもできます。

Dictionary<string, List<int>> subjectScores =new Dictionary<string, List<int>>();

subjectScores.Add("数学", new List<int> { 80, 90, 75 });subjectScores.Add("英語", new List<int> { 70, 85, 92 });

独自クラスを値として指定すれば、複雑な情報も管理できます。

class User{public int Id { get; set; }public string Name { get; set; } = "";public string Email { get; set; } = "";}
var users = new Dictionary<int, User>{{1,new User{Id = 1,Name = "田中",Email = "tanaka@example.com"}}};

キーには、文字列や整数など、値を識別しやすく、内容が変化しない型を使用するのが基本です。

また、同じDictionaryの中では、すべてのキーが同じ型、すべての値が同じ型でなければなりません。

次のコードでは、値の型がintなので、文字列は登録できません。

var scores = new Dictionary<string, int>();

scores.Add("国語", 80);

// コンパイルエラー// scores.Add("数学", "90");

複数の異なる型をまとめて保存するために、値の型をobjectにすることも可能です。

var data = new Dictionary<string, object>{{ "Name", "田中" },{ "Age", 30 },{ "IsActive", true }};

ただし、値を取り出すときに型の確認や変換が必要になるため、特別な理由がなければ具体的な型や独自クラスを指定したほうが安全です。

3. Dictionaryに要素を追加する方法

C#のDictionaryに要素を追加する主な方法は、次の3つです。

  • Addメソッドを使う

  • インデクサーを使う

  • TryAddメソッドを使う

それぞれ、すでに同じキーが登録されている場合の動作が異なります。

追加方法キーが未登録の場合キーが登録済みの場合
Add新しい要素を追加例外が発生
インデクサー新しい要素を追加値を上書き
TryAdd新しい要素を追加してtrueを返す追加せずfalseを返す

違いを理解し、目的に合った方法を使いましょう。

3-1. Addメソッドでキーと値を追加する

Addメソッドは、キーと値を指定して新しい要素を追加する基本的な方法です。

構文は次のとおりです。

dictionary.Add(キー, 値);

実際の使用例を見てみましょう。

var fruits = new Dictionary<string, int>();

fruits.Add("りんご", 150);fruits.Add("みかん", 120);fruits.Add("ぶどう", 500);

登録した要素は、キーを指定して確認できます。

Console.WriteLine(fruits["りんご"]);Console.WriteLine(fruits["ぶどう"]);

実行結果は次のとおりです。

150500

Addメソッドは、「そのキーが未登録であることが前提」の場合に適しています。

たとえば、新しいユーザーIDとユーザー名を登録する場合は、次のように記述できます。

var users = new Dictionary<int, string>();

users.Add(1001, "田中");users.Add(1002, "佐藤");users.Add(1003, "鈴木");

ただし、すでに登録されているキーをAddメソッドで追加すると、ArgumentExceptionが発生します。

3-2. インデクサーを使って要素を追加する

Dictionaryでは、角括弧を使ったインデクサーでも要素を追加できます。

var prices = new Dictionary<string, int>();

prices["りんご"] = 150;prices["みかん"] = 120;

指定したキーが登録されていなければ、新しい要素として追加されます。

Console.WriteLine(prices["りんご"]);

実行結果は次のとおりです。

150

インデクサーの特徴は、すでに同じキーが登録されている場合に、値が上書きされることです。

var prices = new Dictionary<string, int>();

prices["りんご"] = 150;prices["りんご"] = 180;

Console.WriteLine(prices["りんご"]);

実行結果は次のとおりです。

180

最初に登録した150が、後から指定した180に変更されています。

このように、インデクサーは次のような処理に向いています。

  • キーがなければ新しく追加する

  • キーがあれば現在の値を更新する

  • 設定値を登録または変更する

  • 最新の状態で値を保存する

Dictionaryのインデクサーに値を代入した場合、キーが存在しなければ新しい要素が追加され、すでに存在すれば対応する値が置き換えられます。

意図せず既存のデータを上書きする可能性があるため、必ず新規データとして追加したい場合はAddまたはTryAddを使用しましょう。

3-3. TryAddメソッドで重複を避けて追加する

TryAddメソッドは、指定したキーがまだ登録されていない場合にだけ要素を追加します。

追加に成功するとtrue、すでにキーが登録されていて追加できなかった場合はfalseを返します。

var users = new Dictionary<int, string>();

bool result = users.TryAdd(1, "田中");

Console.WriteLine(result);

実行結果は次のとおりです。

True

同じキーをもう一度追加してみます。

bool result = users.TryAdd(1, "佐藤");

Console.WriteLine(result);Console.WriteLine(users[1]);

実行結果は次のとおりです。

False田中

キー1はすでに登録されているため、新しい値の"佐藤"は追加されません。元の値である"田中"も上書きされず、そのまま残ります。

戻り値を利用すると、追加できたかどうかに応じて処理を分けられます。

var products = new Dictionary<string, string>();

if (products.TryAdd("A001", "ノートパソコン")){Console.WriteLine("商品を登録しました。");}else{Console.WriteLine("同じ商品コードが登録されています。");}

同じ商品コードでもう一度実行すると、TryAddfalseを返します。

if (!products.TryAdd("A001", "デスクトップパソコン")){Console.WriteLine("商品コードA001は登録済みです。");}

TryAddは、キーが重複しても例外を発生させず、既存の値も上書きしません。重複する可能性があるデータを安全に追加したい場合に便利です。

3-4. 同じキーを追加すると発生するエラー

Dictionaryでは、同じキーを複数登録できません。

次のコードでは、"A001"というキーを2回追加しています。

var products = new Dictionary<string, string>();

products.Add("A001", "ノートパソコン");products.Add("A001", "デスクトップパソコン");

2回目のAddメソッドを実行すると、ArgumentExceptionが発生します。

An item with the same key has already been added.

このエラーを避けるには、ContainsKeyメソッドを使って、キーが登録されているか確認する方法があります。

var products = new Dictionary<string, string>();

if (!products.ContainsKey("A001")){products.Add("A001", "ノートパソコン");}

すでにキーが登録されている場合の処理も記述できます。

if (!products.ContainsKey("A001")){products.Add("A001", "ノートパソコン");}else{Console.WriteLine("商品コードA001は登録済みです。");}

重複確認と追加をまとめて行いたい場合は、TryAddを使用すると簡潔です。

if (!products.TryAdd("A001", "ノートパソコン")){Console.WriteLine("商品コードA001は登録済みです。");}

登録済みの値を更新したい場合は、インデクサーを使用します。

products["A001"] = "新しいノートパソコン";

つまり、目的に応じて次のように使い分けます。

// 重複時にエラーとして扱うproducts.Add("A001", "ノートパソコン");

// 重複時は追加せず、結果をboolで確認するproducts.TryAdd("A001", "ノートパソコン");

// 重複時は既存の値を上書きするproducts["A001"] = "ノートパソコン";

キーの重複が起こる可能性を考慮せずにAddを使用すると、実行時にプログラムが停止する原因になります。ユーザー入力や外部ファイルなど、内容を完全に予測できないデータを扱う場合は、TryAddContainsKeyによる確認を検討しましょう。

まとめ

C#のDictionaryは、キーと値をセットで管理するためのコレクションです。配列やListが主にインデックスで要素を扱うのに対し、Dictionaryでは商品コード、ユーザーID、名前などの任意のキーを使って値を管理できます。

基本的な宣言方法は次のとおりです。

var dictionary = new Dictionary<string, int>();

作成と同時に要素を登録する場合は、コレクション初期化子を利用できます。

var scores = new Dictionary<string, int>{{ "国語", 80 },{ "数学", 90 }};

要素を追加する方法には、Add、インデクサー、TryAddがあります。

// 同じキーがあると例外が発生dictionary.Add("国語", 80);

// 同じキーがあると値を上書きdictionary["国語"] = 90;

// 同じキーがある場合は追加せずfalseを返すdictionary.TryAdd("国語", 80);

新しいキーであることが保証されている場合はAdd、追加と更新を同じ書き方で行いたい場合はインデクサー、重複による例外や上書きを避けたい場合はTryAddが適しています。

Dictionaryは、キーから対応するデータを扱う多くのC#プログラムで利用されます。まずは文字列と整数のような簡単な組み合わせから試し、それぞれの追加方法による動作の違いを確認してみましょう。