2010-12-09 14 views
22

estoy notando que GetOrAdd() siempre se ejecuta el delegado de la fábrica, incluso cuando el valor existe en el diccionario. Por ejemplo:ConcurrentDictionary.GetOrAdd siempre ejecuta Delegado Método

class Program 
{ 
    private static ConcurrentDictionary<string, string> _cache = new ConcurrentDictionary<string, string>(); 

    static void Main(string[] args) 
    { 
     string value; 

     value = GetValueFromCache("A"); // cache is empty, CacheValueFactory executes, A is added 
     value = GetValueFromCache("A"); // cache contains A, CacheValueFactory executes 
     value = GetValueFromCache("C"); // cache contains A, CacheValueFactory, C is added 
     value = GetValueFromCache("A"); // cache contains A and C, CacheValueFactory executes 
    } 

    private static string GetValueFromCache(string key) 
    { 
     string val = _cache.GetOrAdd(key, CacheValueFactory(key)); 

     return val; 
    } 

    private static string CacheValueFactory(string key) 
    { 
     if (key == "A") 
      return "Apple"; 
     else if (key == "B") 
      return "Banana"; 
     else if (key == "C") 
      return "Cherry"; 

     return null; 
    } 
} 

en la primera llamada a GetValueFromCache ("A"), la caché está vacía y A: Se añade Apple. Al entrar con el depurador, noté que en la segunda y tercera llamadas a GetValueFromCache ("A"), el método CacheValueFactory() siempre se ejecuta. Es esto esperado? Pensé que el método delegado no se ejecutaría si la clave existe en el diccionario.

Respuesta

41

La razón por la que está viendo esto es que no está pasando CacheValueFactory como delegado, sino que evalúa la función rápidamente y pasa el valor resultante. Esto hace que use la sobrecarga que acepta una clave y un valor y no la que acepta una clave y un delegado.

Para utilizar la versión delegado cambiar el código a la siguiente

string val = _cache.GetOrAdd(key, CacheValueFactory); 
+0

Ooops. Tienes razón :) – Bullines

+0

Gotcha! Estaba atrapado en esto también. Gracias. Dooh. – bornfromanegg

2

Si desea manejar escenarios poco más complicadas, por ejemplo, cuando el parámetro no coincide con la clave, se puede utilizar una lambda .

 var keyStr = string.Format("Something_{0}", key); 
     string val = _cache.GetOrAdd(keyStr,_ => CacheValueFactory(key)); 
Cuestiones relacionadas