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

发布于 2024-11-01 20:08:09 字数 1411 浏览 4 评论 0原文

该程序正在使用此实现:

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

但因为我需要在字典中使用 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联系起来的。

The program was working with this implementation:

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

But because I need to use Instrument in Dictionary I've decided to implement 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;
    }
}

Now the program has stopped working. In such or similar places I receive "KeyNotFoundException":

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

Is it possible that some pieces of the code assume that equals and hashcode IS NOT implemented?
Or probably I just implemented them wrong? Sorry I'm not familiar with such advanced features in C# as the last piece of code and don't know how it is connected with equals or hashCode.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

情愿 2024-11-08 20:08:09

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

Your HashCode and Equals methods should depend only on immutable properties - your implementation uses ClassCode and Ticker which both have setters and are therefore mutable.

荒人说梦 2024-11-08 20:08:09

首先,您可以使用包含Key

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

第一个迭代整个键列表 - O(n),而第二个使用 Dictionary 的内置哈希表实现 - O(1)。

第二,检查您的实现中是否存在空引用:

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

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

First, instead of using cache.Keys.Any you can just use ContainsKey.

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

The first iterate over the whole keys list - O(n), while the second uses Dictionary's built in hash table implementation - O(1).

Second, check for null reference in your implementation:

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

Other than that, I can't see a problem.

我的痛♀有谁懂 2024-11-08 20:08:09

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

这是错误的原因。您的类已经具有 Equality 和 GetHashCode 的实现,它们适合、高效且经过测试可在字典中使用。

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

不。您缺少 == 的重载。只有当您使 Instrument 不可变时,它才会可靠。

您最好的做法是覆盖任何这些成员。

另请参阅此 MSDN 建议。注意“平等保证”和

不建议在非不可变类型中重写运算符 ==。

But because I need to use Instrument in Dictionary I've decided to implement equals/hashcode

That's the wrong reason. Your class already has implementations for Equality and GetHashCode that are suitable, efficient and tested for use in a Dictionary.

Have I implemented Equals()/GetHashCode() correctly?

No. You are missing an overload for == to start with. And it will only be reliable when you make Instrument immutable.

Your best course of action is not to override any of those members.

Also see this MSDN advice. Notice the "guarantees of Equals" and

Overriding operator == in non-immutable types is not recommended.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文