给出KeyNotFoundException的C#Dictionary,不知道为什么

时间:2013-07-18 13:53:42

标签: c# dictionary keynotfoundexception

我是一名业余程序员,这似乎是一个简单的修复问题,但我无法弄清楚如何。 下面是C#代码,它不像我想要的那样。我希望这会返回3,而是抛出KeyNotFoundException。列表是相同的,所以不应该返回3?谢谢你的帮助。

Dictionary<object, double> dict = new Dictionary<object, double>();
dict.Add(new List<object>() { "a", "b" }, 3);
double output = dict[new List<object>() { "a", "b" }];

3 个答案:

答案 0 :(得分:8)

List<T>是一种没有特殊Equals实现的引用类型。因此,在您的情况下,虽然两个列表实例具有相同的内容,但它们仍然是不同的实例,因此在密钥查找时不会被视为相等。

根据您的需要,您可以使用不同的解决方案:

  1. 如果您的列表中的项目总是相同,则可以使用元组:

    Dictionary<Tuple<string, string>, double> dict =
        new Dictionary<Tuple<string, string>, double>();
    dict.Add(Tuple.Create("a", "b"), 3);
    double output = dict[Tuple.Create("a", "b")];
    
  2. 如果商品数量不同,您可以创建自己的列表来比较其内容。

答案 1 :(得分:1)

因为有两个不同的对象/实例。

答案 2 :(得分:1)

两个列表都是单独的实例,因此ReferenceEquals返回false,但默认使用。您可以为字典构造函数实现自定义IEqualityComparer<IList<object>>

public class ListComparer : IEqualityComparer<IList<object>>
{
    public bool Equals(IList<object> x, IList<object> y)
    {
        if (x == null || y == null) return false;
        return x.SequenceEqual(y);
    }

    public int GetHashCode(IList<object> list)
    {
        if (list == null) return int.MinValue;
        int hash = 19;
        unchecked // Overflow is fine, just wrap
        {
            foreach (object obj in list)
                if(obj != null)
                    hash = hash + obj.GetHashCode();
        }
        return hash;
    }
}

现在它按预期工作:

var  dict = new Dictionary<List<object>, double>(new ListComparer());
dict.Add(new List<object>() { "a", "b" }, 3);
double output = dict[new List<object>() { "a", "b" }]; // 3.0