2012-09-02 28 views
8

Tengo un escenario simple en el que quiero actualizar el valor de un elemento existente. Solo el método AddOrUpdate ofrece un delegado en el que puedo actualizar el valor anterior. Sin embargo, no quiero agregar nada si la clave no existe. También el método TryUpdate no tiene sobrecargas y puedo obtener el valor anterior. ¿Hay alguna forma de hacerlo con la API actual?¿Hay alguna manera de usar ConcurrentDictionary.TryUpdate con una expresión lambda?

Aquí está la firma Busco:

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

No hay un método que lo haga. ¿Ha considerado agregar un valor especial si la clave no existe y tratar ese valor como si la entrada no estuviera presente? – dtb

+0

@dtb Dado que estoy escribiendo un contenedor para esta clase, no es posible encontrar una clave no válida. Puedo pedirlo específicamente, pero esa no sería mi primera opción. –

+0

En realidad, si está escribiendo un contenedor, en realidad puede almacenar elementos que envuelven el valor, lo que le permite crear su propio valor especial de lápida. Sin embargo, agregaría un costo a cada uso individual. –

Respuesta

13

tienes que estar preparado para recorrer y tal vez llamar a la Func más de una vez (lo mismo que con la sobrecarga de GetOrAdd que utiliza uno). Esto significa que si el Func tiene efectos secundarios, no parecerá ser atómico desde el exterior. Realmente, Func s no deben tener efectos secundarios, pero siempre tienen algún costo por lo que la posibilidad de repetición de llamadas no puede ser ignorada:

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

Como se ha dicho, ya que puede bucle, es sólo atómica como se observa desde el exterior si no hay efectos secundarios en el Func.

(Editar: Eliminando un atajo potencial que en realidad es demasiado tenso como para ser usado en general, y que probablemente muerda a alguien que lo probó).

+0

Excelente respuesta, gracias. –

Cuestiones relacionadas