2012-09-02 23 views
8

Mevcut bir öğenin değerini güncellemek istediğim basit bir senaryo var. Yalnızca AddOrUpdate yöntemi, eski değeri güncelleyebileceğim bir temsilci sunar. Ancak, anahtar yoksa bir şey eklemek istemiyorum. Ayrıca TryUpdate yönteminde eski değeri alabileceğim aşırı yüklenme yok. Mevcut API ile bunu yapmanın bir yolu var mı?ConcurrentDictionary.TryUpdate'i bir lambda ifadesiyle kullanmanın bir yolu var mı?

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

Bunu yapan bir yöntem yoktur. Anahtar mevcut değilse ve bu değer giriş mevcut değilse aynı değeri ele alıyorsa özel bir değer eklemeyi düşündünüz mü? – dtb

+0

@dtb Bu sınıf için bir sarıcı yazdığımdan, geçersiz bir anahtar ile gelmek mümkün değil. Bunu özellikle isteyebilirim ama bu benim ilk tercihim olmayacaktı. –

+0

Aslında, bir sarıcı yazıyorsanız, değeri sarmalayan öğeleri depolayabilir, böylece kendi özel mezar taşı değerinizi oluşturmanıza izin verebilirsiniz. Yine de her kullanım için bir maliyet ekleyecektir. –

cevap

13

Sen döngü hazırlanan ve belki (birini kullanan GetOrAdd ait aşırı ile aynı) bir kez daha Func daha çağrı lazım:

İşte aradığım imzası. Bu, Func'un yan etkilere sahip olması durumunda, dışardan atomik görünmeyeceği anlamına gelir. Gerçekten, Func s yan etkilere sahip olmamalıdır, ama her zaman tekrar aramaların olasılığı göz ardı edilemez bu nedenle bazı maliyeti: gözlenen gibi, sadece atomik döngü var, çünkü

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; 
} 

deyişiyle Func'da hiçbir yan etkisi yoksa dışardan.

(Düzenle: Genelde kullanılması çok zor olan ve muhtemelen deneyen birini ısırması muhtemel bir kısayolun silinmesi).

+0

Harika cevap, teşekkürler. –

İlgili konular