11

我有一个简单的场景,我想更新现有项目的值。只有AddOrUpdate方法提供了一个委托,我可以在其中更新旧值。但是,如果密钥不存在,我不想添加任何内容。TryUpdate方法也没有我可以获得旧值的重载有没有办法用当前的 API 做到这一点?

这是我正在寻找的签名:

bool TryUpdate(TKey key, Func<TValue,TValue> updateValueFactory)
4

1 回答 1

18

您必须准备好循环并且可能Func不止一次调用(与GetOrAdd使用 one 的重载相同)。这意味着如果它Func有副作用,它不会从外部看起来是原子的。真的,Funcs 不应该有副作用,但它们总是有一些成本,所以重复调用的可能性不容忽视:

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.

(编辑:删除一个潜在的捷径,该捷径确实太令人担忧而无法普遍使用,并且可能会咬到尝试过的人)。

于 2012-09-02T23:43:32.440 回答