哈希集中的重复元素

发布于 2024-08-30 10:19:20 字数 1526 浏览 3 评论 0原文

我现在对哈希集有疑问。我有不可变的类并且只包含一个项目,当我将具有相同数据的两个不同类添加到哈希集中时,我将它们都放在集合中。这很奇怪,因为我在基类和超类上都重载了 Equals 和 GetHashCode。

public abstract class Contact :IEquatable<Contact>
{
    public readonly BigInteger Id;

    public Contact(BigInteger id) { this.Id = id; }

    public abstract bool Equals(Contact other);

    public abstract int GetHashCode();

    public abstract bool Equals(object obj);
}

以及继承类:

public class KeyOnlyContact :Contact, IEquatable<KeyOnlyContact>
{
    public KeyOnlyContact(BigInteger id) :base(id) { }

    public override bool Equals(object obj)
    {
        if (obj is KeyOnlyContact)
            return Equals(obj as KeyOnlyContact);
        else if (obj is Contact)
            return Equals(obj as Contact);
        else
            return (this as object).Equals(obj);
    }

    public override bool Equals(Contact other)
    {
        if (other is KeyOnlyContact)
            return Equals(other as KeyOnlyContact);
        else
            return (this as object).Equals(other as object);
    }

    public bool Equals(KeyOnlyContact other)
    {
        return other.Id.Equals(Id);
    }

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

如您所见,所有实际工作都被推迟到 BigInteger(即 id)。这是一个 .net 类,我已确认如果我只是将 BigInteger 添加到哈希集,则不会出现重复。

澄清一下:

BigInteger a;
HashSet<Contact> set;

set.add(new KeyOnlyContact(a));
set.add(new KeyOnlyContact(a));

set.Count == 2

I have a problem with hashsets at the moment. I have classes which are immutable and contain just one item, when I add two different classes with the same data to a hashset, I get them both in the set. This is weird, because I've overloaded Equals and GetHashCode on both the base class and the superclass.

public abstract class Contact :IEquatable<Contact>
{
    public readonly BigInteger Id;

    public Contact(BigInteger id) { this.Id = id; }

    public abstract bool Equals(Contact other);

    public abstract int GetHashCode();

    public abstract bool Equals(object obj);
}

And the inheriting class:

public class KeyOnlyContact :Contact, IEquatable<KeyOnlyContact>
{
    public KeyOnlyContact(BigInteger id) :base(id) { }

    public override bool Equals(object obj)
    {
        if (obj is KeyOnlyContact)
            return Equals(obj as KeyOnlyContact);
        else if (obj is Contact)
            return Equals(obj as Contact);
        else
            return (this as object).Equals(obj);
    }

    public override bool Equals(Contact other)
    {
        if (other is KeyOnlyContact)
            return Equals(other as KeyOnlyContact);
        else
            return (this as object).Equals(other as object);
    }

    public bool Equals(KeyOnlyContact other)
    {
        return other.Id.Equals(Id);
    }

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

As you can see, all the real work is deferred to the BigInteger which is the id. This is a .net class and I have confirmed I don't get duplicate if I just add BigInteger to a hashset.

To clarify:

BigInteger a;
HashSet<Contact> set;

set.add(new KeyOnlyContact(a));
set.add(new KeyOnlyContact(a));

set.Count == 2

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

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

发布评论

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

评论(1

毁我热情 2024-09-06 10:19:20
public abstract int GetHashCode();

您不小心重新声明了 GetHashCode(方法隐藏)。删除此声明,它可能会开始工作。当您的派生类重写 GetHashCode 时,它们会提供版本 - 它们不会重写object.GetHashCode,这就是所需要的。

如果您想要一个抽象的 GetHashCode,也许:

public sealed override int GetHashCode() { return GetHashCodeImpl(); }
protected abstract int GetHashCodeImpl();

现在派生类型必须提供 GetHashCodeImpl,并且它们都映射到 object.GetHashCode 。

public abstract int GetHashCode();

You have accidentally re-declared GetHashCode (method-hiding). Remove this declaration and it might start working. When your derived classed override GetHashCode, they are providing this version - they aren't overriding object.GetHashCode, which is what is required.

If you want an abstract GetHashCode, perhaps:

public sealed override int GetHashCode() { return GetHashCodeImpl(); }
protected abstract int GetHashCodeImpl();

Now the derived types must provide GetHashCodeImpl, and they are all mapped to object.GetHashCode.

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