开发者

Duplicate elements in a hashset

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


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜