开发者

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));
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜