散列集中的重复元素

Mar*_*tin 2 .net c# debugging hashset

我目前有一个hashsets的问题.我有不可变的类,只包含一个项目,当我将两个不同的类添加到相同的数据到一个哈希集时,我在集合中得到它们.这很奇怪,因为我在基类和超类上都重载了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);
}
Run Code Online (Sandbox Code Playgroud)

而继承类:

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();
    }
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,所有实际工作都被推迟到作为id的BigInteger.这是一个.net类,如果我只是将BigInteger添加到一个hashset,我已经确认我不会重复.

澄清:

BigInteger a;
HashSet<Contact> set;

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

set.Count == 2
Run Code Online (Sandbox Code Playgroud)

Mar*_*ell 10

public abstract int GetHashCode();
Run Code Online (Sandbox Code Playgroud)

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

如果你想要一个摘要GetHashCode,或许:

public sealed override int GetHashCode() { return GetHashCodeImpl(); }
protected abstract int GetHashCodeImpl();
Run Code Online (Sandbox Code Playgroud)

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