2010-12-09 14 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 ('ए') के लिए पहली कॉल करने पर, कैश खाली और एक है: एप्पल जोड़ा जाता है। डीबगर के साथ कदम रखते हुए, मैंने देखा कि GetValueFromCache ("ए") के दूसरे और तीसरे कॉल पर, कैशवैल्यू फैक्ट्री() विधि हमेशा निष्पादित होती है। क्या यह उम्मीद है? मैंने सोचा होगा कि अगर कुंजीपटल शब्दकोश में मौजूद है तो प्रतिनिधि विधि निष्पादित नहीं होगी।

उत्तर

41

कारण यह है कि आप इसे देख रहे हैं कि आप एक प्रतिनिधि के रूप में CacheValueFactory पास नहीं कर रहे हैं बल्कि इसके परिणामस्वरूप तत्काल कार्य का मूल्यांकन कर रहे हैं और परिणामस्वरूप मूल्य पारित कर रहे हैं। इससे आपको अधिभार का उपयोग करने का कारण बनता है जो एक कुंजी और मूल्य स्वीकार करता है, न कि जो कुंजी और प्रतिनिधि को स्वीकार करता है।

आप थोड़ा और अधिक जटिल स्थितियों को संभालने के लिए चाहते हैं, तो निम्न

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

ओउप्स। तुम सही हो :) – Bullines

+0

गोटो! मैं भी इस पर अटक गया था। धन्यवाद। Dooh। – bornfromanegg

2

करने के लिए कोड के लिए स्विच, उदाहरण के लिए प्रतिनिधि संस्करण का उपयोग करने के लिए, जब पैरामीटर कुंजी से मेल नहीं खाता, तो आप एक लैम्ब्डा इस्तेमाल कर सकते हैं ।

 var keyStr = string.Format("Something_{0}", key); 
     string val = _cache.GetOrAdd(keyStr,_ => CacheValueFactory(key)); 
संबंधित मुद्दे