【问题标题】:ConcurrentDictionary.GetOrAdd Always Executes Delegate MethodConcurrentDictionary.GetOrAdd 始终执行委托方法
【发布时间】:2010-12-09 16:00:01
【问题描述】:

我注意到 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() 方法。这是预期的吗?我会认为如果字典中存在密钥,则委托方法不会执行。

【问题讨论】:

    标签: c# multithreading .net-4.0


    【解决方案1】:

    您看到这种情况的原因是您没有将CacheValueFactory 作为委托传递,而是立即评估函数并传递结果值。这会导致您使用接受键和值的重载,而不是接受键和委托的重载。

    要使用委托版本,请将代码切换到以下代码

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

    【讨论】:

    • 明白了!我也被困住了。谢谢。呵呵。
    【解决方案2】:

    如果您想处理稍微复杂一些的场景,例如,当参数与键不匹配时,您可以使用 lambda。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-13
      • 1970-01-01
      • 2021-07-05
      • 1970-01-01
      • 2013-07-19
      相关资源
      最近更新 更多