Словарь C# ContainsKey

Моя проблема заключается в том, что ContainsKey всегда возвращает false, даже если ключ был добавлен, а .Equals оценивается как true.

У меня есть следующий класс:

public class StatisticsFilter 
{
    private String someString1;
    private String someString2;
    .....

    public override string ToString()
    {
        return string.Format("{0}-{1}-{2}-{3}-{4}", someString1, someString2, ...)
    }

    public override bool Equals(object obj)
    {            
        return obj.ToString().Equals(ToString());
    }

    public override int GetHashCode()
    {
        return ToString().GetHashCode();
    }
}

Затем у меня есть словарь, который выглядит так:

private readonly IDictionary<StatisticsFilter, Statistics> _filteredStatisticsDict =
            new Dictionary<StatisticsFilter, Statistics>();

....

{
    // ALWAYS EVALUATES TO FALSE!
    if (_filteredStatisticsDict.ContainsKey(statisticsFilter) == false)
    {
         _filteredStatisticsDict.Add(statisticsFilter, new Statistics());
    }
}

person Luke Belbina    schedule 25.05.2011    source источник
comment
Тогда проблема должна заключаться в вашем GetHashCode. Всегда ли он возвращает одно и то же значение для одного и того же экземпляра?   -  person Etienne de Martel    schedule 25.05.2011
comment
Вы передаете ключ или экземпляр класса?   -  person MBen    schedule 25.05.2011
comment
Подождите, ContainsKey(statisticsFilter) оценивается как ложное или ContainsKey(statisticsFilter) == false оценивается как ложное?   -  person Ben Voigt    schedule 25.05.2011


Ответы (2)


Невозможно воспроизвести код, который вы нам дали.

using System;
using System.Collections.Generic;

public class StatisticsFilter 
{
    private String someString1;
    private String someString2;

    public StatisticsFilter(string x, string y)
    {
        this.someString1 = x;
        this.someString2 = y;
    }

    public override string ToString()
    {
        return string.Format("{0}-{1}xyz", someString1, someString2);
    }

    public override bool Equals(object obj)
    {            
        return obj.ToString().Equals(ToString());
    }

    public override int GetHashCode()
    {
        return ToString().GetHashCode();
    }
}

class Test
{
    static void Main()
    {
        var dict = new Dictionary<StatisticsFilter, int>();

        var sf1 = new StatisticsFilter("hello", "there");
        var sf2 = new StatisticsFilter("hello", "there");

        dict[sf1] = 10;
        Console.WriteLine(dict.ContainsKey(sf2)); // Prints true
    }
}
person Jon Skeet    schedule 25.05.2011
comment
Ты прав. Проблема заключалась в том, что StatisticsFilters на самом деле были одним и тем же объектом и были связаны с обновлением ссылки и т. Д. Очень запутанный и запутанный в нашем коде. Спасибо! - person Luke Belbina; 25.05.2011
comment
'@jon Skeet вижу аналогичную проблему, которая у меня есть здесь generic-type" title="как реализовать сравнение в классе, который может принимать любой универсальный тип"> stackoverflow.com/questions/27921694/, пожалуйста, помогите. Благодарю. - person Charles Okwuagwu; 13.01.2015

Ожидаете, что «ToString ()» будет ключом? Я думаю, вы получите желаемый результат, изменив объявление словаря на: Dictionary<string, Statistics>

// not always be false
if (_filteredStatisticsDict.ContainsKey(statistics.ToString() == false)
{
    _filteredStatisticsDict.Add(statisticsFilter.ToString(), newStatisitcs());
}

Если я понимаю, чего вы пытаетесь достичь, это должно сработать. С помощью этого метода ключ словаря основан на содержимом фильтра.

person Jim Reineri    schedule 25.05.2011
comment
да, это сработает, но тогда дело не в том, что на самом деле словарь настолько менее удобочитаем. - person Luke Belbina; 26.05.2011