2012-09-02 10 views
8

私は、既存のアイテムの値を更新する簡単なシナリオを持っています。 AddOrUpdateメソッドのみが、古い値を更新できるデリゲートを提供します。しかし、キーが存在しない場合は何も追加したくありません。また、TryUpdateメソッドには、古い値を取得できるオーバーロードはありません。現在のAPIでそれを行う方法はありますか?ConcurrentDictionary.TryUpdateをラムダ式で使用する方法はありますか?

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

これを行う方法はありません。キーが存在しない場合に特別な値を追加することを検討しましたが、エントリが存在しない場合と同じ値を扱いますか? – dtb

+0

@dtbこのクラスのラッパーを書いているので、無効なキーを提示することはできません。私は特にそれを求めることができますが、それは私の最初の選択ではありません。 –

+0

実際、ラッパーを作成している場合は、値をラップするアイテムを実際に格納できるため、独自の特別な墓石値を作成できます。それはしかし、すべての単一の使用にコストを追加します。 –

答えて

13

あなたがループに用意し、おそらく(1つを使用するGetOrAddの過負荷と同じ)を1回よりも多くのFuncを呼び出すことがあります。

は、ここで私が探していた署名です。これは、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に副作用がない場合は、外部から

(編集:潜在的なショートカットを削除すると、あまりにも一般的に使用される可能性が非常に高く、試した人を噛んでしまう可能性があります)。

+0

偉大な答えは、ありがとう。 –

関連する問題