Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么ConcurrentDictionary有AddOrUpdate和GetOrAdd,而Dictionary没有?_C#_.net_Dictionary_Concurrentdictionary - Fatal编程技术网

C# 为什么ConcurrentDictionary有AddOrUpdate和GetOrAdd,而Dictionary没有?

C# 为什么ConcurrentDictionary有AddOrUpdate和GetOrAdd,而Dictionary没有?,c#,.net,dictionary,concurrentdictionary,C#,.net,Dictionary,Concurrentdictionary,在.NET框架中,有字典和并发字典。 这些提供了类似于添加、删除等方法 我知道当我们设计多线程程序时,为了线程安全,我们使用concurrentdirectionary替换Dictionary 我想知道为什么concurrentdirectionary有AddOrUpdate,GetOrAdd和类似的方法,而Dictionary没有 我们总是喜欢使用下面的代码从字典中获取对象: var dict = new Dictionary<string, object>(); object t

在.NET框架中,有
字典
并发字典
。 这些提供了类似于添加、删除等方法

我知道当我们设计多线程程序时,为了线程安全,我们使用
concurrentdirectionary
替换
Dictionary

我想知道为什么
concurrentdirectionary
AddOrUpdate
GetOrAdd
和类似的方法,而
Dictionary
没有

我们总是喜欢使用下面的代码从
字典
中获取对象:

var dict = new Dictionary<string, object>();
object tmp;
if (dict.ContainsKey("key"))
{
       tmp = dict["key"];
}
else
{
       dict["key"] = new object();
       tmp = new object();
}

我希望.NET有这些方法,但为什么没有呢?

因为这些方法是:

  • 在并发上下文中工作的最低要求。如果不锁定,您不能将
    Get
    Add
    分为两个单独的步骤,并且仍然会产生正确的结果
  • 当为
    Dictionary
    实现时,它隐式地表示某种级别的线程安全性,好像
    Dictionary
    可以正确地处理这个问题。它不能,所以它只是没有实现。这并不能阻止您使用扩展方法来做类似的事情

    public static TValue GetOrAdd<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key, Func<string, TValue> valueGenerator)
    {
        //
        // WARNING: this method is not thread-safe and not intended as such.
        //
        if (!dict.TryGetValue(key, out TValue value))
        {
            value = valueGenerator(key);
    
            dict.Add(key, value);
        }
    
        return value;
    }
    
    public static TValue GetOrAdd(此字典dict dict,TKey key,Func valueGenerator)
    {
    //
    //警告:此方法不是线程安全的,也不是线程安全的。
    //
    如果(!dict.TryGetValue(键,输出值))
    {
    值=值生成器(键);
    dict.Add(键、值);
    }
    返回值;
    }
    

  • ConcurrentDictionary有这些方法,因为它们可以防止竞争条件,Dictionary不需要这些方法,因为它本质上是线程不安全的。谢谢。好的,那么.Net来确保为开发人员提供这些方法是安全的。实际上,对于字典来说,将方法放在其中是有意义的,不是从线程安全的角度,而是从优化的角度。字典已经计算出它期望该项位于哪个存储桶中,而不是哪个存储桶中,然后它可以直接将该项放入该存储桶中。使用tryget+add时,它必须对密钥进行两次散列。从这个角度来看,确实如此,但在这方面,它“仅仅”是一种编码的性能优化。我觉得.NET可以在这方面做一些认真的工作@LasseVågsætherKarlsenAlso,当
    字典
    被引入时,没有lambdas这样的东西。如果总是要传递创建的实例,而不是
    Func
    @LasseV.Karlsen,那么效率可能会降低。因此,如果确实需要,构建“更快”的字典类很容易。我总是想知道为什么那些显而易见的成员被排除在外。
    public static TValue GetOrAdd<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key, Func<string, TValue> valueGenerator)
    {
        //
        // WARNING: this method is not thread-safe and not intended as such.
        //
        if (!dict.TryGetValue(key, out TValue value))
        {
            value = valueGenerator(key);
    
            dict.Add(key, value);
        }
    
        return value;
    }