Словарь C#, дающий 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 ответа

Решение

List<T> является ссылочным типом без специального Equals реализация. Итак, в вашем случае, хотя оба экземпляра вашего списка имеют одинаковое содержимое, они все равно являются разными экземплярами и, как таковые, не считаются равными при поиске ключа.

В зависимости от ваших потребностей вы можете использовать разные решения:

  1. Если в вашем списке всегда одинаковое количество предметов, вы можете использовать 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. Если количество элементов отличается, вы можете создать свой собственный список, который сравнивает его содержание.

Потому что есть два разных объекта / экземпляра.

Оба списка являются отдельными экземплярами, поэтому 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
Другие вопросы по тегам