有效地将项添加到字典中但执行+ =而不是=

时间:2016-04-06 13:53:37

标签: c# dictionary

我有一个将字符串映射到双精度的字典。

我有这一行:

leaves[child.Value] += branchProbability;

崩溃是因为而不是: 如果找不到,则添加默认值0,返回0,将其添加到branchProbability,设置新值= 0 + branchProbability,它通过对引发KeyNotFoundException的键执行get来启动。

我唯一能想到的是:

if(!leaves.ContainsKey(child.Value))
   leaves[child.Value] = branchProbability;
else
   leaves[child.Value] += branchProbability;

但这需要额外查找contains。

在避免包含检查的同时,是否有更有效的方法来执行此操作?

2 个答案:

答案 0 :(得分:2)

以下代码定义(并测试,如果将其粘贴到LinqPad中),这个类将允许您使用+=执行此操作。但是,如果您将字典传递到很多地方,它将无法工作,因为它必须使用new隐藏索引器而不是覆盖它(Dictionary的索引器不是虚拟的)。

解决这个问题的一种方法是创建DefaultingDictionary作为IDictionary<TKey, TValue>的实现者,并在具有私有成员Dictionary的类中,并将所有调用委托给IDictionary上的方法 - 除了索引器,你自己做的。您仍然无法将此传递给期望Dictionary的内容,但您可以更改这些内容以接受IDictionary

void Main()
{
    var dict = new DefaultingDictionary<string, double>();

    dict["one"] = 1;

    dict["one"] += 1;
    dict["two"] += 1;

    Console.WriteLine(dict["one"]);
    Console.WriteLine(dict["two"]);
}

class DefaultingDictionary<TKey, TValue> : Dictionary<TKey, TValue>
{
    public new TValue this[TKey key]
    {
        get
        {
            TValue v;
            if(TryGetValue(key, out v))
            {
                return v;
            }
            return default(TValue);
        }

        set
        {
            base[key] = value;
        }
    }
}

老实说,这只是能够做+=事情的很多工作。真的,你应该做检查。这没有性能优势,只会让你的代码变得更复杂。如果您进行检查,那么阅读它的人就会明白究竟发生了什么。

答案 1 :(得分:-3)

我不确定你能做多少,也许介绍一个三元运算符而不是if..else会在论文上看起来不错。但就可读性而言,我会建议你采用的方式。

leaves[child.value] = leaves.ContainsKey(child.value) 
                     ? leaves[child.value] + branchProbability 
                     : branchProbability;