重写的Equals方法不会被HashSet调用

时间:2013-10-02 07:31:17

标签: c#

我有一个名为'x'的类,它覆盖了Equals(),如下所示:

    public override bool Equals(object obj)
    {
        if(obj is x)
        {
            return ((obj as x).key == this.key);
        }
        return false;
    }

当以下扩展方法尝试使用上述覆盖进行比较时,不会使用Equals():

    public static bool Contains(this HashSet<x> set, char key)
    {
        x SearchKey = new x(key);
        return set.Contains(SearchKey);
    }

只有在我修改extensio方法中的第一行时才能得到预期的行为:

x SearchKey = new x(key);

你能解释一下这种行为吗?

我曾预料到,Equals()将被调用x本身的实例,因为它是Object的一个子集。我错过了什么?

3 个答案:

答案 0 :(得分:2)

首先,正如其他人所指出的那样,你也必须覆盖GetHashCode。类似的东西:

public override int GetHashCode()
{
    return key.GetHashCode();
}

答案 1 :(得分:2)

您还必须实施IEquatable<T>。集合转到IEquatable接口进行比较,这是类型安全的,在比较值类型时不会导致装箱/取消装箱。

如前所述,您也应该覆盖GetHashCode。 如果您使用像resharper这样的产品,该工具可以为您自动生成此产品。常见的模式类似于:

    public virtual bool Equals(Entity other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return other.Id.Equals(Id);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (!(obj is Entity)) return false;
        return Equals((Entity)obj);
    }

    public override int GetHashCode()
    {
        return Id.GetHashCode();
    }

使用interface方法执行所有基于类型的东西,并使用重写的Equals(object)来检查类型不变条件,然后转换并重定向到接口方法。

有关生成哈希代码的一般最佳做法,请参阅John Skeets回答here

答案 2 :(得分:0)

您可能必须覆盖GetHashCode;) 在hashSet中,比较方法是哈希码。

相关问题