【问题标题】:Method to Add new or update existing item in Dictionary在字典中添加新项目或更新现有项目的方法
【发布时间】:2011-05-13 19:17:14
【问题描述】:

在一些遗留代码中,我看到了以下扩展方法,以方便添加新的键值项或更新值(如果键已存在)。

方法 1(旧代码)。

public static void CreateNewOrUpdateExisting<TKey, TValue>(
    this IDictionary<TKey, TValue> map, TKey key, TValue value)
{            
    if (map.ContainsKey(key))
    {
        map[key] = value;
    }
    else
    {
        map.Add(key, value);
    }
}

不过,我已经检查过map[key]=value 的工作完全相同。即该方法可以替换为下面的方法二。

方法二。

public static void CreateNewOrUpdateExisting<TKey, TValue>(
    this IDictionary<TKey, TValue> map, TKey key, TValue value)
{
    map[key] = value;
}

现在,我的问题是.. 如果我用 Method-2 替换 Method-1 会有什么问题吗?它会在任何可能的情况下中断吗?

另外,我认为这曾经是 HashTable 和 Dictionary 之间的区别。 HashTable 允许更新项目,或使用索引器添加新项目,而 Dictionary 不允许!在 C# > 3.0 版本中是否消除了这种差异?

这个方法的目的是如果用户再次发送相同的key-value不会抛出异常,该方法应该只是用新的值更新条目,如果已​​经发送了新的key-value对则创建一个新的条目方法。

【问题讨论】:

    标签: c# dictionary


    【解决方案1】:

    如果我将 Method-1 替换为 Method-2 会有什么问题吗?

    不,只需使用map[key] = value。这两个选项是等价的。


    关于Dictionary&lt;&gt;Hashtable:当你启动Reflector 时,你会看到两个类的索引器设置器都调用this.Insert(key, value, add: false); 并且add 参数负责在插入重复键时引发异常。所以这两个类的行为是相同的。

    【讨论】:

      【解决方案2】:

      没有问题。我什至会从源代码中删除CreateNewOrUpdateExisting 并直接在您的代码中使用map[key] = value,因为这是惯用的C#; C# 开发人员通常会知道map[key] = value 表示添加或更新。

      【讨论】:

        【解决方案3】:

        老问题,但我觉得我应该添加以下内容,甚至更多,因为在编写问题时.net 4.0 已经启动。

        从 .net 4.0 开始,命名空间 System.Collections.Concurrent 包含线程安全的集合。

        集合System.Collections.Concurrent.ConcurrentDictionary&lt;&gt; 完全符合您的要求。它具有AddOrUpdate() 方法以及线程安全的附加优势。

        如果您处于高性能场景并且不处理多个线程,那么map[key] = value 已经给出的答案会更快。

        在大多数情况下,这种性能优势是微不足道的。如果是这样,我建议使用 ConcurrentDictionary,因为:

        1. 它在框架中 - 经过更多测试,您不是必须维护代码的人
        2. 它是可扩展的:如果你切换到多线程,你的代码已经准备好了

        【讨论】:

          【解决方案4】:

          在功能上,它们是等价的。

          性能方面map[key] = value 会更快,因为您只进行一次查找而不是两次。

          风格方面,越短越好:)

          在大多数情况下,代码似乎在多线程上下文中运行良好。但是,如果没有额外的同步,它是不是线程安全的。

          【讨论】:

            【解决方案5】:

            唯一的问题可能是如果有一天

            地图[键] = 值

            将转变为 -

            地图[键]++;

            这将导致 KeyNotFoundException。

            【讨论】:

              【解决方案6】:

              我知道它不是 Dictionary&lt;TKey, TValue&gt; 类,但是你可以避免 KeyNotFoundException 同时增加如下值:

              dictionary[key]++; // throws `KeyNotFoundException` if there is no such key  
              

              通过使用ConcurrentDictionary<TKey, TValue> and its really nice method AddOrUpdate().

              让我举个例子:

              var str = "Hellooo!!!";
              var characters = new ConcurrentDictionary<char, int>();
              foreach (var ch in str)
                  characters.AddOrUpdate(ch, 1, (k, v) => v + 1);
              

              【讨论】:

              • 是的,看起来很不错...但是ConcurrentDictionary 为多线程(即锁)增加了很多同步开销。因此会对性能产生重大影响。
              猜你喜欢
              • 2020-03-04
              • 2023-03-15
              • 1970-01-01
              • 1970-01-01
              • 2021-10-13
              • 2011-09-18
              • 1970-01-01
              • 2020-05-13
              • 1970-01-01
              相关资源
              最近更新 更多