4

我有我的自定义类的 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 类中实现一些比较接口方法会更优雅。

有可能还是我只是不明白某事?

谢谢。

4

4 回答 4

4

覆盖时Equals,您还应该覆盖GetHashCode. HashSet(和其他散列结构,如Dictionary)将首先为您的对象计算一个散列码,以便在将元素与Equals.

public override int GetHashCode()
{
    return StringComparer.InvariantCulture.GetHashCode(this.Name);
}
于 2013-03-16T15:01:13.940 回答
3

您不必实现任何接口(尽管IEquatable<T>)是鼓励的。当您在未指定相等比较器的情况下创建哈希集时,它默认为 using 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);
    }
}
于 2013-03-16T15:06:55.243 回答
1

你介意也覆盖一下.GetHashCode()吗?

这是参考

于 2013-03-16T15:00:19.770 回答
0

您必须使用覆盖GetHashCodeEquals覆盖。

Object.Equals 方法

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

于 2013-03-16T15:00:26.267 回答