2010-12-09 75 views
22

我注意到GetOrAdd()始終執行工廠委託,即使該值存在於字典中。例如:ConcurrentDictionary.GetOrAdd始終執行委託方法

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

第一次調用GetValueFromCache(「A」)時,緩存爲空,並且A:Apple被添加。加入調試器,我注意到在對GetValueFromCache(「A」)的第二次和第三次調用中,CacheValueFactory()方法始終執行。這是預期的嗎?如果密鑰存在於字典中,我會認爲委託方法不會執行。

回答

41

你看到這個的原因是你沒有通過CacheValueFactory作爲委託,而是立即評估函數並傳遞結果值。這會導致您使用接受鍵和值的重載,而不是接受鍵和委託的重載。

要使用代理的版本。如果你想處理稍微複雜場景的代碼轉換爲以下

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

Ooops。你是對的:) – Bullines 2010-12-09 16:05:40

2

,例如,當參數不匹配的鑰匙,你可以使用lambda 。

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