即使受ContainsKey保护,字典也会引发参数异常

时间:2015-06-26 09:26:25

标签: c# dictionary

在生产中,这段代码(C#,.NET 4.5.1)正在抛出一个ArgumentException来表明这一点 An item with the same key has already been added.

代码:

public MyClass()
{
   this.MyContent = new Dictionary<string, string>();            
}

public IDictionary<string, string> MyContent { get; private set; }

public void AddOrUpdateDictionary(string key, string value)
{
    if (this.MyContent.ContainsKey(key))
    {
        this.MyContent[key] = string.Concat(this.MyContent[key], value);
    }
    else
    {
        this.MyContent.Add(key, value);
    }
}

但是,我无法在单元测试中重新创建错误。例如。这表现得如预期的那样 -

[TestMethod]
public void AddOrUpdateDictionary_WhenAddingSecondValue_ValueIsAppended()
{
    const string InputValue1 = "Value1";
    const string InputValue2 = "Value2";
    string expectedValue = string.Concat(InputValue1, InputValue2);

    var obj = new MyClass();
    obj.AddOrUpdateDictionary("Key", InputValue1);
    obj.AddOrUpdateDictionary("Key", InputValue2);

    Assert.AreEqual(expectedValue, obj.MyContent["Key"]);
}

造成这种情况的原因是什么?我认为ContainsKey会使代码安全。

我错过了一些奇怪的线程吗?此代码位于MVC站点中的模型上,没有任何实例是静态的。

2 个答案:

答案 0 :(得分:2)

Assuming the problem is thread related and it is allowed to change the type of dictionary, you could use a ConcurrentDictionary. It exposes a method (AddOrUpdate) that can do exactly what's intended: either add the value or refactor the value based on the present value:

    class MyClass
    {
        public MyClass()
        {
            this.content = new ConcurrentDictionary<string, string>();
        }

        ConcurrentDictionary<string, string> content;
        public IDictionary<string, string> MyContent { get { return content; } }

        public void AddOrUpdateDictionary(string key, string value)
        {
            content.AddOrUpdate(key, value, (k, contentValue) => string.Concat(contentValue, value));   
        }
    }

答案 1 :(得分:0)

You may want to use ConcurrentDictionary<T1, T2>

So it would be like:

    public void AddOrUpdateDictionary(string key, string value)
    {
        if (this.MyContent.ContainsKey(key))
        {
            this.MyContent[key] = string.Concat(this.MyContent[key], value);
        }
        else
        {
            this.MyContent.AddOrUpdate(key, value, (x, y) => value);
        }
    }