复杂类型的HashSet ExceptWith

本文关键字:ExceptWith HashSet 类型 复杂 | 更新日期: 2023-09-27 18:04:08

我有自定义类的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);

但这不起作用。我想这行不通,因为我有复杂类型。问题是:是否有一些接口需要在顶点类中实现才能使它工作?我知道,虽然创建HashSet我可以传递一个EqualityComparer,但在我看来,在顶点类中实现一些比较接口方法会更优雅。

是可能的还是我真的不明白?

谢谢。

复杂类型的HashSet ExceptWith

当覆盖Equals时,您也应该覆盖GetHashCodeHashSet(和其他哈希结构,如Dictionary)将首先计算一个哈希码为您的对象在一个结构中定位,然后与Equals比较元素。

public override int GetHashCode()
{
    return StringComparer.InvariantCulture.GetHashCode(this.Name);
}

您不必实现任何接口(尽管鼓励使用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);
    }
}

你介意覆盖.GetHashCode()吗?

你必须用Equals覆盖来覆盖GetHashCode

对象。=方法:

覆盖Equals(Object)的类型也必须覆盖GetHashCode;否则,哈希表可能无法正常工作。