keyが存在しない場合はデフォルト値を返すDictionaryのメソッド
ってなんで無いんでしょうかね。
普通に、アクセスしようとすると
var dict = new Dictionary<string,string>();
var t = dict["test"];//↑で作ったばかりなので入ってるはずもなく、KeyNotFoundException
この時点でnull返してくれたりすればいいのになぁ。と思わなくもないんですが。
まぁ、想像するとまだnullableが無かったころの名残なのかな。と。
stringみたいな参照型ならいいけれど、Dictionary<string,int>
みたいに、Valueがプリミティブ型だった場合に0返したとしてそれが本当のValueの0なのか、Keyが無かったからデフォルト値の0なのかが判別つかないからかな。
いや、そもそも、参照型だとしても明示的にvalueにnull入れる場合もあるので・・・?
そう考えると無いのもしょうがないな。とは思います。が、不便なものは不便。
一応、先にContainsKey
でKeyの存在チェックをしたり、TryGetValue
する。という手もあるんですが、無駄に行数はかさむし、直感的じゃなかったりするので、ここは拡張メソッドの出番でしょう。
こんな拡張クラスを作っておくと便利
public static class DictionaryExtensions {
/// <summary>
/// 値を取得、keyがなければデフォルト値を設定し、デフォルト値を取得
/// </summary>
public static TV GetOrDefault<TK, TV>(this Dictionary<TK, TV> dic, TK key,TV defaultValue = default(TV))
{
TV result;
return dic.TryGetValue(key, out result) ? result : defaultValue;
}
}
DictionaryにGetOrDefault
という名前のメソッドを拡張メソッドとして生やします。
これで、
var dict = new Dictionary<string,string>();
//var t = dict["test"];//↑で作ったばかりなので入ってるはずもなく、KeyNotFoundException
var t = dict.GetOrDefault("test"); //default値を指定しない場合はdefault(KV),KV=stringなので、stringのデフォ値のnullがtに入る
var t2 = dict.GetOrDefault("test2","入ってなかったよ"); //default値を明示的に指定した場合は、keyが存在しない場合にそれが使用される。
と、なり、みんなハッピーです。
###2020/01/27追記
C#7.0 から out var(out変数宣言)
が使えるので、上記 TryGetValue
はさらに簡略化して書けるようになります。
(詳しくは→ TryGetComponentとout、out var のお話 などをどうぞ(ダイマ
public static class DictionaryExtensions {
/// <summary>
/// 値を取得、keyがなければデフォルト値を設定し、デフォルト値を取得
/// </summary>
public static TV GetOrDefault<TK, TV>(this Dictionary<TK, TV> dic, TK key,TV defaultValue = default(TV))
{
return dic.TryGetValue(key, out var result) ? result : defaultValue;
}
}
単行になりました。 なら、こうも書けますね。(ついでにdefaultの書き方も変更)
public static class DictionaryExtensions {
/// <summary>
/// 値を取得、keyがなければデフォルト値を設定し、デフォルト値を取得
/// </summary>
public static TV GetOrDefault<TK, TV>(this Dictionary<TK, TV> dic, TK key,TV defaultValue = default) => dic.TryGetValue(key, out var result) ? result : defaultValue;
}
まぁ、(多分)速度に違いはないのであとは見やすさ、わかりやすさ。そして場合によってはチームの規約に従うしかないのでTPOに応じて適切なものを使いましょう。
ではでは。