辞書.TryGetValue() / ContainsKey()
| 対応: | C# 2.0(2005) |
|---|
辞書から安全に値を取得する『TryGetValue()』と、指定したキーが存在するか確認する『ContainsKey()』メソッドです。
構文
using System.Collections.Generic; // キーが存在する場合は true と値を返します。存在しない場合は false と既定値を返します。 dict.TryGetValue(TKey key, out TValue value) // 指定したキーが辞書に存在する場合は true を返します。 dict.ContainsKey(TKey key) // 指定した値が辞書に存在する場合は true を返します(キーとは違い O(n) の処理です)。 dict.ContainsValue(TValue value)
メソッド一覧
| メソッド | 概要 |
|---|---|
| TryGetValue(TKey key, out TValue value) | キーが存在する場合は true を返し、out パラメーターに値を格納します。存在しない場合は false を返し、value には型の既定値が入ります。 |
| ContainsKey(TKey key) | 辞書に指定したキーが含まれる場合は true を返します。ハッシュを使って O(1) で検索します。 |
| ContainsValue(TValue value) | 辞書に指定した値が含まれる場合は true を返します。内部を順番に走査するため O(n) になります。 |
サンプルコード
Program.cs
using System;
using System.Collections.Generic;
Dictionary<string, int> scores = new Dictionary<string, int>
{
{ "狡噛慎也", 85 },
{ "常守朱", 92 },
{ "宜野座伸元", 78 }
};
// TryGetValue() で安全に値を取得します。
if (scores.TryGetValue("常守朱", out int tsunemoriScore))
{
Console.WriteLine($"常守朱さんの点数: {tsunemoriScore}"); // 常守朱さんの点数: 92
}
// キーが存在しない場合は false を返します。
if (!scores.TryGetValue("征陸智己", out int masaokaScore))
{
Console.WriteLine($"征陸さんのデータがありません。値: {masaokaScore}"); // 値: 0(既定値)
}
// ContainsKey() で存在確認をしてから追加します。
string newKey = "征陸智己";
if (!scores.ContainsKey(newKey))
{
scores.Add(newKey, 70);
Console.WriteLine($"{newKey} を追加。");
}
// ContainsValue() で値の存在を確認します。
Console.WriteLine(scores.ContainsValue(92)); // True
Console.WriteLine(scores.ContainsValue(100)); // False
コンパイルして実行すると次のようになります。
dotnet run 常守朱さんの点数: 92 征陸さんのデータがありません。値: 0 征陸智己 を追加。 True False
実践パターン: キャッシュとしての利用
TryGetValue() はキャッシュの読み書きパターンによく使われます。キーが存在すればキャッシュから取得し、なければ計算してキャッシュに追加します。
CacheSample.cs
using System;
using System.Collections.Generic;
Dictionary<string, string> cache = new Dictionary<string, string>();
string GetData(string key)
{
if (cache.TryGetValue(key, out string cached))
{
Console.WriteLine($"キャッシュヒット: {key}");
return cached;
}
string value = $"データ:{key}(計算済み)";
cache[key] = value;
Console.WriteLine($"キャッシュなし: {key} を計算。");
return value;
}
Console.WriteLine(GetData("狡噛慎也"));
Console.WriteLine(GetData("常守朱"));
Console.WriteLine(GetData("狡噛慎也")); // 2回目はキャッシュから
コンパイルして実行すると次のようになります。
dotnet run キャッシュなし: 狡噛慎也 を計算。 データ:狡噛慎也(計算済み) キャッシュなし: 常守朱 を計算。 データ:常守朱(計算済み) キャッシュヒット: 狡噛慎也 データ:狡噛慎也(計算済み)
よくあるミス
よくあるミス: インデクサーで存在しないキーを取得する
dict[key] で存在しないキーを取得すると KeyNotFoundException がスローされます。キーの存在が不確かな場合は TryGetValue() を使ってください。
using System;
using System.Collections.Generic;
// NG: 存在しないキーをインデクサーで取得する
Dictionary<string, int> scores = new Dictionary<string, int>
{
{ "狡噛慎也", 85 }
};
// int score = scores["征陸智己"]; // KeyNotFoundException!
修正後は次の通りです。
using System;
using System.Collections.Generic;
// OK: TryGetValue() で安全に取得する
Dictionary<string, int> scores = new Dictionary<string, int>
{
{ "狡噛慎也", 85 }
};
if (scores.TryGetValue("征陸智己", out int score))
{
Console.WriteLine($"スコア: {score}");
}
else
{
Console.WriteLine("データが見つかりません。");
}
修正後は次の通りです。
dotnet run データが見つかりません。
概要
辞書のインデクサー dict[key] で存在しないキーを取得すると KeyNotFoundException がスローされます。キーが存在するか確かめてから取得したい場合は、if + ContainsKey() の2段階よりも『TryGetValue()』の1回の呼び出しで済む方が効率的です。
辞書のキー・値一覧の取得とループには『Keys / Values / foreach』を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。