2

現在、ハッシュセットに問題があります。不変で1つのアイテムしか含まないクラスがあります。同じデータを持つ2つの異なるクラスをハッシュセットに追加すると、両方がセットに含まれます。基本クラスとスーパークラスの両方で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();
    }

ご覧のとおり、実際の作業はすべて、IDであるBigIntegerに延期されます。これは.netクラスであり、BigIntegerをハッシュセットに追加するだけで重複しないことを確認しました。

明確にするために:

BigInteger a;
HashSet<Contact> set;

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

set.Count == 2
4

1 に答える 1

10
public abstract int GetHashCode();

誤って再宣言しましたGetHashCode(メソッド非表示)。この宣言を削除すると、機能し始める可能性があります。派生したクラス化された場合、それらはこのバージョンoverride GetHashCodeを提供します-オーバーライドされません。これが必要です。object.GetHashCode

要約が必要な場合はGetHashCode、おそらく:

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

ここで、派生型はを提供する必要GetHashCodeImplがあり、それらはすべてにマップされobject.GetHashCodeます。

于 2010-04-29T21:47:23.163 に答える