参考
この記事は、以下の動画を参考にしています。
詳しくは、動画をご覧ください。
状況
public static TValue GetOrAdd<TKey, TValue>(
this Dictionary<TKey, TValue> dict, TKey key, TValue value)
where TKey : notnull
{
if (dict.TryGetValue(key, out var result)) // 辞書内を検索
return result;
dict[key] = value; // ここでも辞書内を検索
return value;
}
- 辞書に、指定したキーに対応するエントリーあれば、その値を戻す
- キーに対応するエントリーがなければ、指定した値でキーに対応するエントリーを作り、その値を戻す
というメソッド。
このとき、1. と 2. の2回、辞書内の検索が実行されてしまう。
これを、1回の検索で済むようにできないものか。
解決法
public static TValue GetOrAdd<TKey, TValue>(
this Dictionary<TKey, TValue> dict, TKey key, TValue value)
where TKey : notnull
{
ref var val = ref CollectionsMarshal.GetValueRefOrAddDefault(dict, key, out var exists);
if (exists)
{
return val;
}
val = value; // 単なる代入
return value;
}
System.Runtime.InteropServices.CollectionsMarshal
クラスのGetValueRefOrAddDefault
メソッドを使う。(.NET 9から)
CollectionsMarshal.GetValueRefOrAddDefault
メソッドが、
- 辞書に、指定したキーに対応するエントリーあれば、その参照を戻す
- キーに対応するエントリーがなければ、エントリーを作り、その参照を戻す
まで行ってくれる。
これで、辞書を二度検索する必要がなくなる。
他にも
CollectionsMarshal.GetValueRefOrNullRef
メソッドでは、キーに対応するエントリーがなかった場合、null
参照を戻す。