存在するかどうかわからないディクショナリからキーを取得する場合、通常、TryGetValue
+ get indexerの代わりにContainsKey
を使用して、キーを2回チェックするオーバーヘッドを回避します。言い換えれば、これ:
string password;
if (accounts.TryGetValue(username, out password))
{
// use the password
}
これよりも望ましいでしょう:
if (accounts.ContainsKey(username))
{
string password = accounts[username];
}
キーを値に設定する前に既に存在しているかどうかを確認したい場合はどうすればよいですか?たとえば、新しいパスワードで上書きする前に、ユーザー名が存在するかどうかを確認したいと思います。
if (!accounts.ContainsKey(username))
{
accounts.Add(username, password);
}
else
{
Console.WriteLine("Username is taken!");
}
対
// this doesn't exist
if (!accounts.TrySetValue(username, password))
{
Console.WriteLine("Username is taken!");
}
これを行うContainsKey
およびAdd
の代わりにパフォーマンスがありますか?
オーバーライドしたくない場合は、TryGetValue
のような独自の拡張メソッドを記述する方が良いと思います。標準的な方法はありません。
OR
CuncurrentDictionaryを使用します。 TryAdd メソッドがありますが、同期のオーバーヘッドが発生します。
だから、簡単な答え-いいえ、そのような方法はありません。
新しい名前の挿入が一般的なケースであり、重複を挿入しようとするのはまれなケースだと思う場合は、例外をキャッチするオーバーヘッドを使用したいだけです。
try
{
accounts.Add(username, password);
}
catch (ArgumentException)
{
Console.WriteLine("Username is taken!");
}
既存のキーでAdd
を呼び出すと、ArgumentException
がスローされます。重複が頻繁にある場合でも、ContainsKey
チェックよりもパフォーマンスが高い可能性があります。
必要に応じて独自の拡張機能を作成する傾向があります。
たとえば、GetValueOrDefault
は次のようになります。
public static V GetValueOrDefault<K, V>(this IDictionary<K, V> @this, K key, Func<V> @default)
{
return @this.ContainsKey(key) ? @this[key] : @default();
}
次のように使用できます。
var password = accounts.GetValueOrDefault(username, () => null);
if (password != null)
{
//do stuff
}
またはSetValueIfExists
:
public static V SetValueIfExists<K, V>(this IDictionary<K, V> @this, K key, V value)
{
if (@this.ContainsKey(key))
{
@this[key] = value;
}
}
またはSetValueIfNotExists
:
public static V SetValueIfNotExists<K, V>(this IDictionary<K, V> @this, K key, V value)
{
if ([email protected](key))
{
@this[key] = value;
}
}
私はこれに遅れていることを知っていますが、インデクサーが設定される前にトリックを使用してカウントを保存し、インデクサーが設定された後にカウントを確認できます。カウントが同じ場合は、キーをオーバーライドしています。それ以外の場合は、新しいマッピングを追加しています。
public static bool AddOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue>
dictionary, TKey key, TValue value)
{
var countBefore = dictionary.Count;
dictionary[key] = value;
return countBefore != dictionary.Count;
}