2010-12-09 16 views
22

Ich stelle fest, dass GetOrAdd() den Factory-Delegaten immer ausführt, auch wenn der Wert im Wörterbuch vorhanden ist. Zum Beispiel:ConcurrentDictionary.GetOrAdd führt immer die Delegate-Methode aus

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

Nach dem ersten Aufruf von GetValueFromCache ("A"), ist der Cache leer und A: Apple hinzugefügt. Als ich mit dem Debugger eintrat, bemerkte ich, dass die CacheValueFactory() -Methode beim zweiten und dritten Aufruf von GetValueFromCache ("A") immer ausgeführt wird. Wird das erwartet? Ich hätte gedacht, dass die Delegate-Methode nicht ausgeführt werden würde, wenn der Schlüssel im Wörterbuch vorhanden ist.

Antwort

41

Der Grund dafür ist, dass Sie CacheValueFactory nicht als Delegat übergeben, sondern die Funktion sofort bewerten und den resultierenden Wert übergeben. Dies führt dazu, dass Sie die Überladung verwenden, die einen Schlüssel und einen Wert akzeptiert und nicht die, die einen Schlüssel und einen Delegaten akzeptiert.

Um die Delegierten Version schalten Sie den Code wie folgt

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

Hoppla. Du hast Recht :) – Bullines

+0

Gotcha! Ich war auch dabei. Vielen Dank. Dooh. – bornfromanegg

2

zu verwenden Wenn Sie etwas kompliziertere Szenarien behandeln möchten, zum Beispiel, wenn der Parameter den Schlüssel nicht übereinstimmen, können Sie eine Lambda verwenden .

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