この記事ではC#のDictionaryクラスについて簡単なコードで解説します。
Dictioanryの基本
Dictionaryクラスとは、配列やListクラスのようにオブジェクトをグループ化する仕組みで、ジェネリックコレクションの一種です。
配列やListクラスでは要素番号(インデックス)で要素の値にアクセスするのに対して、Dictionaryクラスはキー(key)と値(value)のペアを持ち、キーにより値にアクセスします。このためキーは重複することはできません。
このようなキーと値を持つ配列を連想配列とも言います。通常の配列のインデックスは数字ですが、連想配列であるDictionaryクラスでは任意の型を持つキーがインデックスの代わりになります。
Dictionaryの宣言と初期化
Dictionaryオブジェクトは下記のように宣言します。
var オブジェクト名 = new Dictionary<Tkey, TValue>();
もちろんvarではなくDictionary<TKey,TValue>でもOKです。
実際の宣言と初期化の方法を見てみましょう。
コード
using System;
using System.Collections.Generic;
internal class Program
{
static void Main(string[] args)
{
//空のDictionaryの宣言と初期化
var dic1 = new Dictionary<string, double>();
//宣言と初期化子を使った初期化
var dic2 = new Dictionary<string, double>(){
{ "Japan", 1.2610 },
{ "USA", 3.3290},
{ "India", 13.9040 }
};
}
}上記コードは宣言と初期化をしているだけです。
まずC#でDictionaryクラスを使うためには、2行目のようにusingディレクティブに、
using System.Collections.Generic;
を記述します。書かない場合には宣言時に完全修飾名が必要です。
9行目では空のDictionaryオブジェクトのインスタンスを生成しています。このDictinaryのキーはstring型、値はdouble型になります。varはDictionary<string, double>とすることももちろんできます。
12~16行目でも同じくDictionaryオブジェクトのインスタンスを生成していますが、13~15行目でキーと値のペアで初期化子を使って初期化しています。
Dictionaryのキーによるアクセス
Dictionaryオブジェクトにはキーによりアクセスします。配列のインデックスの代わりにキーを用いるイメージです。具体的には下記のとおりです。
コード
using System;
using System.Collections.Generic;
internal class Program
{
static void Main(string[] args)
{
var dic = new Dictionary<string, double>(){
{ "Japan", 1.2610 },
{ "USA", 3.3290},
{ "India", 13.9040 }
};
string jpn = "Japan";
Console.WriteLine("{0}の人口は{1}億人です", jpn, dic[jpn]);
dic[jpn] = 2;
Console.WriteLine("{0}の人口が{1}億人に増えました", jpn, dic[jpn]);
}
}出力結果
Japanの人口は1.261億人です
Japanの人口が2億人に増えました
上記コードの15行目のdic[jpn]でDhictionaryの値にアクセスしています。jpn=”Japan”なので、dic[“Japan”]としているのと同じことです。9行目の初期化子によって、キー”Japan”に対応する値は1.2610となっていますので、出力結果の通りとなります。
17行目のようにキーを指定して値を変更することもできます。
Dictionaryのforeach文による繰り返し処理
次にforeachによりDictionaryオブジェクトの中身を表示してみましょう。
コード
using System;
using System.Collections.Generic;
internal class Program
{
static void Main(string[] args)
{
var dic = new Dictionary<string, double>(){
{ "Japan", 1.2610 },
{ "USA", 3.3290},
{ "India", 13.9040 }
};
foreach (var item in dic)
{
Console.WriteLine("{0}の人口は{1}億人です", item.Key, item.Value);
}
}
}出力結果
Japanの人口は1.261億人です
USAの人口は3.329億人です
Indiaの人口は13.904億人です
上記コードの14行目のitemはvarとして型推論していますが、実際にはDictionaryオブジェクトの要素の型はKeyValuePair<TKey, TValue>という型です。この場合にはKeyValuePair<string, double>という型になります。このKeyValuePair<TKey, TValue>型の変数は読み取り専用のKeyプロパティとValueプロパティがあり、それぞれDictionaryオブジェクトの要素のキーと値を取得することができます。
ちなみに次のようにDictionaryオブジェクトの要素(KeyValuePair<TKey, TValue>型)をタプルで受け取ることもできます。
コード
using System;
using System.Collections.Generic;
internal class Program
{
static void Main(string[] args)
{
var dic = new Dictionary<string, double>(){
{ "Japan", 1.2610 },
{ "USA", 3.3290},
{ "India", 13.9040 }
};
foreach (var (key, val) in dic)
{
Console.WriteLine("{0}の人口は{1}億人です", key, val);
}
}
}出力結果
Japanの人口は1.261億人です
USAの人口は3.329億人です
Indiaの人口は13.904億人です
上記コードの14行目ではタプルで受け取っています。foreach(var (key, val) in dic)の部分は、
foreach((string key, double val) in dic)
としても同じです。
ToStringメソッドを使って要素をリストアップする
またリストアップするだけなら、ToString()メソッドも使用できます。
コード
using System;
using System.Collections.Generic;
internal class Program
{
static void Main(string[] args)
{
var dic = new Dictionary<string, double>(){
{ "Japan", 1.2610 },
{ "USA", 3.3290},
{ "India", 13.9040 }
};
foreach (var item in dic)
{
Console.WriteLine(item.ToString());
}
}
}出力結果
[Japan, 1.261]
[USA, 3.329]
[India, 13.904]
Dictionaryクラスのプロパティ
Countプロパティで要素数を取得する
CountプロパティはDictionaryオブジェクトの要素数を取得します。
下記コードでは14行目で要素数を取得しています。
コード
using System;
using System.Collections.Generic;
internal class Program
{
static void Main(string[] args)
{
var dic = new Dictionary<string, double>(){
{ "Japan", 1.2610 },
{ "USA", 3.3290},
{ "India", 13.9040 }
};
Console.WriteLine("{0}の要素数は{1}です", nameof(dic), dic.Count);
}
}出力結果
dicの要素数は3です
Keysプロパティでキーを格納したコレクションを取得する
Keysプロパティは、キーを格納したコレクションを返します。このコレクションの型はDictionary<TKey,TValue>.KeyCollection型です。
コード
using System;
using System.Collections.Generic;
internal class Program
{
static void Main(string[] args)
{
var dic = new Dictionary<string, double>(){
{ "Japan", 1.2610 },
{ "USA", 3.3290},
{ "India", 13.9040 }
};
var keys = dic.Keys;
foreach(var key in keys)
{
Console.WriteLine(key);
}
}
}出力結果
Japan
USA
India
上記コードの14行目でキーを格納したコレクションを取得し、変数keysに代入しています。ここで変数keysはvarにより型推論されていますが、この場合の型はDictionary<string, double>.KeyCollection型になります。
ここで得たコレクションをforeach文で出力していますが、ここでのkeyはvarで型推論されていますが、これの型はDictionaryオブジェクトのキーの型であるstring型になります。
Valuesプロパティで値を格納したコレクションを取得する
Valuesプロパティは、値を格納したコレクションを返します。このコレクションの型はDictionary<TKey,TValue>.ValueCollection型です。
コード
using System;
using System.Collections.Generic;
internal class Program
{
static void Main(string[] args)
{
var dic = new Dictionary<string, double>(){
{ "Japan", 1.2610 },
{ "USA", 3.3290},
{ "India", 13.9040 }
};
var vals = dic.Values;
foreach(var val in vals)
{
Console.WriteLine(val);
}
}
}出力結果
1.261
3.329
13.904
上記コードの14行目でキーを格納したコレクションを取得し、変数keysに代入しています。ここで変数keysはvarにより型推論されていますが、この場合の型はDictionary<string, double>.ValueCollection型になります。
ここで得たコレクションをforeach文で出力していますが、ここでのvalはvarで型推論されていますが、これの型はDictionaryオブジェクトの値の型であるdouble型になります。
Dictionaryクラスのメソッド
Addメソッドで要素を追加する
AddメソッドによりDictionaryオブジェクトに要素(キーと値のペア)を追加できます。Addメソッドの引数は(key, value)になります。
コード
using System;
using System.Collections.Generic;
internal class Program
{
static void Main(string[] args)
{
var dic = new Dictionary<string, double>();
dic.Add("Japan", 1.2610);
dic.Add("USA", 3.3290);
dic.Add("India", 13.9040);
foreach (var item in dic)
{
Console.WriteLine(item.ToString());
}
}
}出力結果
[Japan, 1.261]
[USA, 3.329]
[India, 13.904]
Removeメソッドで指定したキーを持つ要素を削除する
Removeメソッドは2種類あります。
指定したキーを持つ要素を削除する
ひとつめのRemoveメソッドは、単純に指定したキーを持つ要素を削除します。メソッドの引数は一つで、削除する要素のキーを指定します。戻り値はbool型で、正常に削除された場合にはTrueを、それ以外の場合にはFalseを返します。
コード
using System;
using System.Collections.Generic;
internal class Program
{
static void Main(string[] args)
{
var dic = new Dictionary<string, double>(){
{ "Japan", 1.2610 },
{ "USA", 3.3290},
{ "India", 13.9040 }
};
bool flgUSA= dic.Remove("USA");
bool flgBRZ = dic.Remove("Brazil");
Console.WriteLine("USAは正常に削除されたので{0}です",flgUSA);
Console.WriteLine("Brazilは存在しないため削除できないので{0}です",flgBRZ);
foreach (var (key, val) in dic)
{
Console.WriteLine("{0}の人口は{1}億人です", key, val);
}
}
}
出力結果
USAは正常に削除されたのでTrueです
Brazilは存在しないため削除できないのでFalseです
Japanの人口は1.261億人です
Indiaの人口は13.904億人です
上記コードでは14,15行目でRemoveメソッドを使用しています。14行目でキーが”USA”の要素を削除しています。削除されているのでRemoveメソッドの戻り値はtrueとなり、flgUSAはtrueとなります。15行目ではキーが”Brazil”の要素を削除しようとしていますが、キーが”Brazil”の要素はありません。キーが存在しないので、正常に削除できていないため、Removeメソッドの戻り値はfalseとなり、flgBRZはfalseとなります。
指定したキーを持つ要素を削除して、その値を取得する
ふたつめのRemoveメソッドは、outキーワードを使って削除した要素の値を受け取る点でひとつめのRemoveメソッドと異なります。
このRemoveメソッドの引数は二つあり、一つ目の引数には削除する要素のキーを指定し、二つ目の引数にはoutキーワードを用いて削除した要素の値を受け取る変数を指定します。戻り値はbool型で、正常に削除された場合にはTrueを、それ以外の場合にはFalseを返します。
コード
using System;
using System.Collections.Generic;
internal class Program
{
static void Main(string[] args)
{
var dic = new Dictionary<string, double>(){
{ "Japan", 1.2610 },
{ "USA", 3.3290},
{ "India", 13.9040 }
};
string rmvkey;
rmvkey = "USA";
bool flgUSA= dic.Remove(rmvkey,out double popUSA);
Console.WriteLine("USAは正常に削除されたので{0}です", flgUSA);
Console.WriteLine("削除された{0}の人口は{1}億人でした", rmvkey, popUSA);
rmvkey = "Brazil";
bool flgBRZ = dic.Remove(rmvkey, out double popBRZ);
Console.WriteLine("Brazilは存在しないため削除できないので{0}です",flgBRZ);
Console.WriteLine("削除できなかった{0}の人口は{1}億人でした", rmvkey, popBRZ);
foreach (var (key, val) in dic)
{
Console.WriteLine("{0}の人口は{1}億人です", key, val);
}
}
}出力結果
USAは正常に削除されたのでTrueです
削除されたUSAの人口は3.329億人でした
Brazilは存在しないため削除できないのでFalseです
削除できなかったBrazilの人口は0億人でした
Japanの人口は1.261億人です
Indiaの人口は13.904億人です
上記コードでは17行目でRemoveメソッドを使用してキー”USA”を持つ要素を削除し、outキーワードを使ってpopUSAに削除された要素の値を受け取っています。正常に削除されているためRemoveメソッドの戻り値はtrueです。戻り値は18行目で、popUSAの値は19行目で表示しています。
次に22行目でキーが”Brazil”の要素を削除しています。しかしキーが”Brazil”の要素は存在しませんので正常に削除できず、Removeメソッドの戻り値はfalseとなります。outキーワードを使ってpopBRZで削除された要素の値を受け取ろうとしていますが、削除できていないので、double型の規定値の0が入ります。戻り値は23行目で、popBRZの値は24行目で表示しています。
Clearメソッドですべての要素を削除する
Clearメソッドでは、すべての要素を削除します。
コード
using System;
using System.Collections.Generic;
internal class Program
{
static void Main(string[] args)
{
var dic = new Dictionary<string, double>(){
{ "Japan", 1.2610 },
{ "USA", 3.3290},
{ "India", 13.9040 }
};
Console.WriteLine("Clear前の{0}の要素数は{1}です", nameof(dic), dic.Count);
dic.Clear();
Console.WriteLine("Clear後の{0}の要素数は{1}です", nameof(dic), dic.Count);
}
}出力結果
Clear前のdicの要素数は3です
Clear後のdicの要素数は0です
上記コードでは14行目でClearメソッドを使用しています。15行目でClearメソッド後の要素数を表示していますが、0となっています。
ContainsKeyメソッドでキーの有無を調べる
指定したキーを持つ要素がDictionaryオブジェクトに含まれているかを調べます。引数はひとつで有無を調べるキーを指定します。戻り値はbool型で、指定したキーを持つ要素が存在すればtrueを、存在しない場合にはfalseを返します。
コード
using System;
using System.Collections.Generic;
internal class Program
{
static void Main(string[] args)
{
var dic = new Dictionary<string, string>(){
{ "花子", "赤組" }, { "太郎", "青組"}, { "梅子", "緑組" },{"次郎","赤組"}
};
string str;
str = "花子";
Console.WriteLine("{0}を検索しました.結果は{1}です.", str, dic.ContainsKey(str));
str = "桃子";
Console.WriteLine("{0}を検索しました.結果は{1}です.", str, dic.ContainsKey(str));
}
}出力結果
花子を検索しました.結果はTrueです.
桃子を検索しました.結果はFalseです.
ContainsValueメソッドで値の有無を調べる
指定した値を持つ要素がDictionaryオブジェクトに含まれているかを調べます。引数はひとつで有無を調べる値を指定します。戻り値はbool型で、指定した値を持つ要素が存在すればtrueを、存在しない場合にはfalseを返します。
コード
using System;
using System.Collections.Generic;
internal class Program
{
static void Main(string[] args)
{
var dic = new Dictionary<string, string>(){
{ "花子", "赤組" }, { "太郎", "青組"}, { "梅子", "緑組" },{"次郎","赤組"}
};
string str;
str = "赤組";
Console.WriteLine("{0}を検索しました.結果は{1}です.", str, dic.ContainsValue(str));
str = "黄組";
Console.WriteLine("{0}を検索しました.結果は{1}です.", str, dic.ContainsValue(str));
}
}出力結果
赤組を検索しました.結果はTrueです.
黄組を検索しました.結果はFalseです.
GetEnumeratorメソッドによる列挙子の取得とキーと値の列挙
GetEnumeratorメソッドを使って列挙子を取得することができます。下記コードでは、列挙子を使ってキーと値を列挙します。
コード
using System;
using System.Collections.Generic;
internal class Program
{
static void Main(string[] args)
{
var dic = new Dictionary<string, double>();
dic.Add("Japan", 1.2610);
dic.Add("USA", 3.3290);
dic.Add("India", 13.9040);
//列挙子の取得
var e = dic.GetEnumerator();
while (e.MoveNext() == true)
{
Console.WriteLine("{0}の人口は{1}億人です", e.Current.Key, e.Current.Value);
}
e.Dispose();
}
}出力結果
Japanの人口は1.261億人です
USAの人口は3.329億人です
Indiaの人口は13.904億人です
14行目で列挙子eを取得しています。取得直後は、列挙子は最初の要素の前に位置していますので、16行目のMoveNextメソッドで次の要素に移動しています。MoveNextメソッドは、列挙子が次の要素に移動した場合にはtrue、次の要素に移動できなかった場合にはfalseを返します。whileループの条件式はe.MoveNext() == trueとなっているので、次の要素がなくなりfalseとなった時点でループから抜けます。
また18行目のCurrentプロパティでは、列挙子の現在位置の要素を取得します。この要素は、KeyValuePair<TKey, TValue>型なので、読み取り専用のKeyプロパティとValueプロパティでキーと値を取得しています。
20行目のDisposeメソッドでリソースを解放しています。
TryAddメソッドで指定したキーと値の追加を試みる
TryAddメソッドでは、指定したキーと値の追加を試みます。TryAddメソッドの引数は二つあり、ひとつめは追加を試みるキー、ふたつめは追加を試みる値です。戻り値はbool型で、正常にキーと値のペアが追加されればtrueを返し、それ以外の場合にはfalseを返します。
コード
using System;
using System.Collections.Generic;
internal class Program
{
static void Main(string[] args)
{
var dic = new Dictionary<string, string>(){
{ "花子", "赤組" }, { "太郎", "青組"}, { "梅子", "緑組" }
};
string name, team;
bool result;
name = "次郎"; team = "赤組";
result = dic.TryAdd(name, team);
if(result) Console.WriteLine("{0}が{1}として正常に追加されました", name , dic[name]);
else Console.WriteLine("{0}が{1}に追加できませんでした", name, team);
name = "太郎"; team = "赤組";
result = dic.TryAdd(name, team);
if (result) Console.WriteLine("正常に{0}が{1}として追加されました", name, dic[name]);
else Console.WriteLine("{0}を{1}に追加できませんでした", name, team);
}
}出力結果
次郎が赤組として正常に追加されました
太郎を赤組に追加できませんでした
上記コードでは、16行目と22行目でTryAddメソッドを使用しています。16行目では正常にキーと値を追加できるのでtrueを返してます。22行目では、重複したキーがあるので追加できずfalseを返しています。
TryGetValueメソッドで指定したキーを持つ要素の値の取得を試みる
TryGetValueメソッドは、指定したキーを持つ要素の値の取得を試みるメソッドです。引数は2つあり、ひとつめはキーを指定します。ふたつめの引数にはoutキーワードを用いて取得を試みた要素の値を受け取る変数を指定します。戻り値はbool型で、正常に取得できればtrueを、それ以外の場合にはfalseを返します。
コード
using System;
using System.Collections.Generic;
internal class Program
{
static void Main(string[] args)
{
var dic = new Dictionary<string, double>();
dic.Add("Japan", 1.2610);
dic.Add("USA", 3.3290);
dic.Add("India", 13.9040);
string str;
bool result;
str = "USA";
result = dic.TryGetValue(str, out double popUSA);
if (result) Console.WriteLine("{0}の人口は{1}億人です", str, popUSA);
else Console.WriteLine("{0}の人口は取得できませんでした", str);
str = "Brazil";
result = dic.TryGetValue(str, out double popBRZ);
if (result) Console.WriteLine("{0}の人口は{1}億人です", str, popBRZ);
else Console.WriteLine("{0}の人口は取得できませんでした", str);
}
}出力結果
USAの人口は3.329億人です
Brazilの人口は取得できませんでした
上記コードでは、17行目と22行目で値の取得を試みています。17行目では値が取得できたのでresultにはtrueが入ります。22行目ではキーが”Brazil”という要素は存在しないため値は取得できずresultにはfalseが入ります。
終わりに
ここではDictionaryについて説明しました。Dictionaryクラスのキーにはクラスやタプルなども使用できます。使い方によっては便利です。

