在添加键之前检查键是否存在于字典中的最佳方法
本文关键字:字典 方法 最佳 于字典 添加 检查 存在 是否 | 更新日期: 2023-09-27 18:06:51
当从字典中获取不确定是否存在的键时,通常使用TryGetValue
而不是ContainsKey
+ get索引器,以避免两次检查键的开销。换句话说,就是:
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
做到这一点?
如果您认为插入新名称将是常见的情况,而尝试插入重复名称将是罕见的情况,您可能只想使用捕获异常的开销。
try
{
accounts.Add(username, password);
}
catch (ArgumentException)
{
Console.WriteLine("Username is taken!");
}
如果用一个已存在的键调用Add
,将抛出一个ArgumentException
。即使您有频繁的重复,这仍然可能比您的ContainsKey
检查性能更高。
如果您不想重写,我认为最好编写自己的扩展方法,如TryGetValue
。没有标准方法。
或
使用CuncurrentDictionary,它有TryAdd方法,但是你会有同步开销
所以,简单的答案——不,没有这样的方法
我倾向于根据需要编写自己的扩展。
例如,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 (!@this.ContainsKey(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;
}