C# Dictionary giving a KeyNotFoundException, not sure why

770 Views Asked by At

I'm an amateur programmer, and this seems like a simple problem to fix, but I just can't figure out how. Below is C# code that isn't acting like I want it to. I expect for this to return 3, yet instead throws a KeyNotFoundException. The Lists are the same, so shouldn't it be returning 3? Thanks for any help.

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

There are 3 best solutions below

2
On BEST ANSWER

List<T> is a reference type without a special Equals implementation. So, in your case, while both of your list instances have the same content, they are still different instances and as such are not considered equal upon key lookup.

Depending on your needs, you could use different solutions:

  1. If you always have the same amount of items in your list, you can use a Tuple:

    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. If the amount of items differ, you can create your own list that compares its content.

0
On

Because there are two different objects/instances.

0
On

Both lists are separate instances, so ReferenceEquals returns false, but that is used by default. You could implement a custom IEqualityComparer<IList<object>> for the dictionary constructor:

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;
    }
}

Now it works as expected:

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