2012-09-02 15 views
8

Mam prosty scenariusz, w którym chcę zaktualizować wartość istniejącego elementu. Tylko metoda AddOrUpdate oferuje delegata, w którym mogę zaktualizować starą wartość. Jednak nie chcę dodawać niczego, jeśli klucz nie istnieje. Również metoda TryUpdate nie ma przeciążenia, że ​​mogę uzyskać starą wartość. Czy istnieje sposób, aby to zrobić przy użyciu bieżącego interfejsu API?Czy istnieje sposób użycia ConcurrentDictionary.TryUpdate z wyrażeniem lambda?

Oto podpis szukam:

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

Nie ma metody, która to robi. Czy rozważałeś dodanie wartości specjalnej, jeśli klucz nie istnieje i traktujesz tę wartość tak samo, jak gdyby wpis nie był obecny? – dtb

+0

@dtb Odkąd piszę o tej klasie, nie można wymyślić nieprawidłowego klucza. Mogę o to konkretnie poprosić, ale to nie byłby mój pierwszy wybór. –

+0

Właściwie, jeśli piszemy wrappera, faktycznie można przechowywać elementy, które zawijają wartość, dzięki czemu można utworzyć własną specjalną wartość nagrobka. Dodałoby to jednak koszt każdego użycia. –

Odpowiedz

13

Musisz być przygotowany do pętli i może wywołać więcej Func niż raz (tak samo jak w przypadku przeciążenia GetOrAdd który wykorzystuje jeden). Oznacza to, że jeśli Func ma efekty uboczne, nie wydaje się być atomowy z zewnątrz. Naprawdę, Func s nie powinna mieć skutków ubocznych, ale zawsze jakieś koszty więc możliwość ponownych połączeń nie mogą być ignorowane:

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

jak powiedział, bo to może pętla, to tylko atomowy obserwowany z zewnątrz, jeśli nie ma żadnych skutków ubocznych w Func.

(Edycja: usunięcie potencjalnego skrótu, który jest naprawdę zbyt bolesny, aby go powszechnie używać i prawdopodobnie ugryzie kogoś, kto go wypróbował).

+0

Świetna odpowiedź, dziękuję. –

Powiązane problemy