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



程序使用以下实现:

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

但是因为我需要在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;
    }
}

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

if (cache.Keys.Any(instrument => instrument.Ticker == newTicker && instrument.ClassCode == newClassCode))

是否有可能某些代码假设equals和hashcode没有实现?或者我只是执行错了?对不起,我不熟悉c#中作为最后一段代码的高级功能,也不知道它如何与equals或hashCode连接。

你的HashCode和Equals方法应该只依赖于不可变的属性——你的实现使用ClassCode和Ticker,它们都有setter,因此是可变的。

首先,您可以使用ContainsKey代替cache.Keys.Any

bool contains = cache.ContainsKey(
    new Instrument { Ticker = newTicker, ClassCode = newClassCode });

第一个遍历整个键列表- O(n),而第二个使用字典的内置哈希表实现- O(1)。

第二个,在你的实现中检查null引用:

public override bool Equals(object obj)
{
    if (obj == null)
        return false;
    Instrument instrument = obj as Instrument;
    if (instrument == null)
        return false;
    // 1. string.Equals can handle null references.
    // 2. object.ReferenceEquals for better preformances when it's the same object
    return (object.ReferenceEquals(this, instrument)) ||
        (string.Equals(ClassCode, instrument.ClassCode) &&
        string.Equals(Ticker, instrument.Ticker));
}
public override int GetHashCode()
{
    int hash = 13;
    if (ClassCode != null)
        hash = (hash * 7) + ClassCode.GetHashCode();
    if (Ticker!= null)
        hash = (hash * 7) + Ticker.GetHashCode();
    return hash;
}

除此之外,我看不出有什么问题

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

那是错误的理由。你的类已经有了equal和GetHashCode的实现,它们在Dictionary中使用是合适的、有效的和经过测试的。

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

。您错过了==开始时的过载。只有当你让Instrument不可变时,它才会可靠。

最好的做法是而不是重写这些成员。

请参阅此MSDN建议。注意" Equals的保证"和

不建议在非不可变类型中重写operator ==。

最新更新