哈希集中的重复元素
我现在对哈希集有疑问。我有不可变的类并且只包含一个项目,当我将具有相同数据的两个不同类添加到哈希集中时,我将它们都放在集合中。这很奇怪,因为我在基类和超类上都重载了 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您不小心重新声明了
GetHashCode
(方法隐藏)。删除此声明,它可能会开始工作。当您的派生类重写 GetHashCode
时,它们会提供此版本 - 它们不会重写object.GetHashCode
,这就是所需要的。如果您想要一个抽象的 GetHashCode,也许:
现在派生类型必须提供 GetHashCodeImpl,并且它们都映射到 object.GetHashCode 。
You have accidentally re-declared
GetHashCode
(method-hiding). Remove this declaration and it might start working. When your derived classedoverride GetHashCode
, they are providing this version - they aren't overridingobject.GetHashCode
, which is what is required.If you want an abstract
GetHashCode
, perhaps:Now the derived types must provide
GetHashCodeImpl
, and they are all mapped toobject.GetHashCode
.