在Dictionary中添加新项或更新现有项的方法

时间:2010-11-22 11:46:02

标签: c# dictionary

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

方法-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完成了同样的工作。也就是说,此方法可以替换为下面的方法-2。

方法-2。

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允许更新项目,或使用索引器添加新项目,而词典则不行!在C#&gt;中消除了这种差异吗? 3.0版本?

如果用户再次发送相同的键值,则此方法的目标不是抛出异常,该方法应该只使用新值更新条目,并且如果已发送新的键值对则创建新条目方法。

6 个答案:

答案 0 :(得分:195)

  

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

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


关于Dictionary<>Hashtable:当您启动Reflector时,您会看到两个类的索引器设置器都调用this.Insert(key, value, add: false);add参数负责抛出插入重复键时的异常。所以两个类的行为都是一样的。

答案 1 :(得分:37)

没问题。我甚至会从源代码中删除CreateNewOrUpdateExisting并在代码中直接使用map[key] = value,因为这样更易读,因为开发人员通常会知道map[key] = value的含义。

答案 2 :(得分:17)

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

从.net 4.0开始,存在名称空间System.Collections.Concurrent,其中包含线程安全的集合。

集合System.Collections.Concurrent.ConcurrentDictionary<>完全符合您的要求。它具有AddOrUpdate()方法,并具有线程安全的附加优势。

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

在大多数情况下,此性能优势无关紧要。如果是这样,我建议使用ConcurrentDictionary,因为:

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

答案 3 :(得分:6)

从功能上讲,它们是等价的。

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

风格方面,越短越好:)

在大多数情况下,代码似乎在多线程上下文中工作正常。但是,如果没有额外的同步,线程安全。

答案 4 :(得分:1)

唯一的问题可能是有一天

map [key] =值

将转换为-

map [key] ++;

这将导致KeyNotFoundException。

答案 5 :(得分:0)

我知道它不是Dictionary<TKey, TValue>类,但是您可以在增加像这样的值时避免使用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);