我是否正确实现了Equals()/ GetHashCode()?

jav*_*red 8 .net c# gethashcode

该计划正在实施此实施:

class Instrument
{
    public string ClassCode { get; set; }
    public string Ticker { get; set; }
    public override string ToString()
    {
        return " ClassCode: " + ClassCode + " Ticker: " + Ticker + '.';
    }
}
Run Code Online (Sandbox Code Playgroud)

但是因为我需要在Dictionary中使用Instrument,所以我决定实现equals/hashcode:

class Instrument
{
    public string ClassCode { get; set; }
    public string Ticker { get; set; }
    public override string ToString()
    {
        return " ClassCode: " + ClassCode + " Ticker: " + Ticker + '.';
    }

    public override bool Equals(object obj)
    {
        if (obj == null)
            return false;

        Instrument instrument = obj as Instrument;
        if (instrument == null)
            return false;

        return ((ClassCode.Equals(instrument.ClassCode)) && (Ticker.Equals(instrument.Ticker));
    }

    public override int GetHashCode()
    {
        int hash = 13;
        hash = (hash * 7) + ClassCode.GetHashCode();
        hash = (hash * 7) + Ticker.GetHashCode();
        return hash;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在该程序已停止工作.在这样或类似的地方,我收到"KeyNotFoundException":

if (cache.Keys.Any(instrument => instrument.Ticker == newTicker && instrument.ClassCode == newClassCode))
Run Code Online (Sandbox Code Playgroud)

是否有可能某些代码段假定equals和hashcode未实现?或者我可能只是错误地实现了它们?抱歉,我不熟悉C#中的这些高级功能作为最后一段代码,不知道它是如何与equals或hashCode连接的.

Joe*_*Joe 7

您的HashCode和Equals方法应仅依赖于不可变属性 - 您的实现使用ClassCode和Ticker,它们都具有setter并因此是可变的.

  • @HuBeZa:假设您将对象放入Dictionary中,它将根据其计算的哈希值分配给bucket,比如说它转到了#1桶.现在,您在刚刚放入的对象中修改Ticker和/或ClassCode,并使用.Contains执行查找.然后,Dictionary调用GetHashCode来确定它应该搜索我们的对象的哪个存储桶 - 并且由于修改了值,它假定它是#2而不是#1.它检查桶#2 - 你的对象不在那里.包含您在字典中放入的对象的false返回.这就是您希望不可变成员生成哈希的原因. (5认同)