除了HashSet中的复杂类型

时间:2013-03-16 14:58:06

标签: c# equals hashset

我有自定义类的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 个答案:

答案 0 :(得分:4)

覆盖Equals时,您还应覆盖GetHashCodeHashSet(以及其他散列结构,如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)

您必须覆盖GetHashCode覆盖Equals

Object.Equals Method

  

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