我有自定义类的HashSet:
public class Vertex
{
public string Name;
public override bool Equals(object obj)
{
var vert = obj as Vertex;
if (vert !=null)
{
return Name.Equals(vert.Name, StringComparison.InvariantCulture);
}
return false;
}
}
现在我有两个哈希集
HashSet<Vertex> hashSet1 = new HashSet<Vertex>();
HashSet<Vertex> hashSet1 = new HashSet<Vertex>();
现在我想在hashSet1中只有不在hashSet2中的顶点 所以我使用ExceptWith方法
hashSet1.ExceptWith(hashSet2);
但这不起作用。 我认为这不起作用,因为我有复杂的类型。 所以问题是:是否需要在Vertex类中实现一些接口才能使这个功能正常工作? 我知道在创建HashSet时我可以传递一个EqualityComparer,但在我看来,在Vertex类中实现一些比较接口方法会更优雅。
是否有可能或者我只是不理解某事?
感谢。
答案 0 :(得分:4)
覆盖Equals
时,您还应覆盖GetHashCode
。 HashSet
(以及其他散列结构,如Dictionary
)将首先计算对象的哈希码,以便在将元素与Equals
进行比较之前将其定位在结构中。
public override int GetHashCode()
{
return StringComparer.InvariantCulture.GetHashCode(this.Name);
}
答案 1 :(得分:2)
您不必实施任何界面(尽管IEquatable<T>
)。当你创建一个哈希集而没有指定相等比较器时,它默认使用EqualityComparer<T>.Default
,它要求对象本身相互比较它们(特殊套管空引用)。
但是,在您的情况下,您的平等合同已被破坏,因为您没有覆盖GetHashCode
。以下是我将如何修复您的类型:
public class Vertex : IEquatable<Vertex>
{
public string Name { get; private set; }
public Vertex(string name)
{
Name = name;
}
public override int GetHashCode()
{
return StringComparer.InvariantCulture.GetHashCode(Name);
}
public override bool Equals(object obj)
{
return Equals(obj as Vertex);
}
public bool Equals(Vertex obj)
{
return obj != null && StringComparer.InvariantCulture.Equals(Name, obj.Name);
}
}
答案 2 :(得分:1)
你介意覆盖.GetHashCode()
吗?
这是reference。
答案 3 :(得分:0)