我有一个简单的场景,我想更新现有项目的值。只有AddOrUpdate方法提供了一个委托,我可以在其中更新旧值。但是,如果密钥不存在,我不想添加任何内容。此外TryUpdate方法没有重载,我可以获得旧值。有没有办法用当前的API做到这一点?
这是我要找的签名:
bool TryUpdate(TKey key, Func<TValue,TValue> updateValueFactory)
答案 0 :(得分:16)
你必须准备循环并且可能多次调用Func
(与使用一个GetOrAdd
的重载相同)。这意味着如果Func
具有副作用,则它看起来不是来自外部的原子。实际上,Func
s不应该有副作用,但它们总是有一些成本,所以不能忽略重复调用的可能性:
public static bool TryUpdate<TKey, TValue>(
this ConcurrentDictionary<TKey, TValue> dict,
TKey key,
Func<TValue, TValue> updateFactory)
{
TValue curValue;
while(dict.TryGetValue(key, out curValue))
{
if(dict.TryUpdate(key, updateFactory(curValue), curValue))
return true;
// if we're looping either the key was removed by another thread,
// or another thread changed the value, so we start again.
}
return false;
}
如上所述,因为它可以循环,如果Func
中没有副作用,它只是从外部观察到的原子。
(编辑:删除一个非常普遍使用的潜在捷径,并且可能会咬人尝试过它。)