Повторяющиеся элементы в хэш-сет - PullRequest
2 голосов
/ 30 апреля 2010

У меня проблема с хэш-сетами на данный момент. У меня есть классы, которые являются неизменными и содержат только один элемент. Когда я добавляю два разных класса с одинаковыми данными в хэш-набор, я получаю их оба в наборе. Это странно, потому что я перегружен 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, который является идентификатором. Это класс .net, и я подтвердил, что я не получу дубликат, если просто добавлю BigInteger в хэш-набор.

Для уточнения:

BigInteger a;
HashSet<Contact> set;

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

set.Count == 2

1 Ответ

10 голосов
/ 30 апреля 2010
public abstract int GetHashCode();

Вы случайно повторно объявили GetHashCode (скрытие метода). Удалите эту декларацию, и она может начать работать. Когда ваши производные классифицируют override GetHashCode, они предоставляют эту версию - они не переопределяют object.GetHashCode, что и требуется.

Если вы хотите реферат GetHashCode, возможно:

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

Теперь производные типы должны предоставлять GetHashCodeImpl, и все они отображаются на object.GetHashCode.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...