ConcurrentDictionary.GetOrAdd Always Executes Delegate Method
I'm noticing that GetOrAdd() always executes the factory delegate, even when the value exists in the dictionary. For example:
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
开发者_StackOverflow社区 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;
}
}
Upon the first call to GetValueFromCache("A"), the cache is empty and A:Apple is added. Stepping in with the debugger, I noticed that on the second and third calls to GetValueFromCache("A"), the CacheValueFactory() method always executes. Is this expected? I would've thought that the delegate method wouldn't execute if the key exists in the dictionary.
The reason you're seeing this is that you are not passing CacheValueFactory
as a delegate but instead evaluating the function promptly and passing the resulting value. This causes you to use the overload which accepts a key and value and not the one which accepts a key and delegate.
To use the delegate version switch the code to the following
string val = _cache.GetOrAdd(key, CacheValueFactory);
If you want to handle slightly more complicated scenarios, for example, when the parameter doesn't match the key, you could use a lambda.
var keyStr = string.Format("Something_{0}", key);
string val = _cache.GetOrAdd(keyStr,_ => CacheValueFactory(key));
精彩评论