7

我有一个名为“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 的子集。我错过了什么?

4

3 回答 3

3

首先,正如其他人指出的那样,您也必须覆盖GetHashCode。就像是:

public override int GetHashCode()
{
    return key.GetHashCode();
}
于 2013-10-02T07:49:59.713 回答
2

You have to Implement IEquatable<T> as well. Collections go to the IEquatable interface for comparison, which is type safe and will not cause boxing/unboxing when comparing value types.

As mentioned before you should override GetHashCode too. If you are using a product like resharper the tool can auto-generate this for you. A common pattern is something like:

    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();
    }

Where you use the interface method to do all type based stuff and the overridden Equals(object) to check for type invariant conditions only, then cast and redirect to the interface method.

For general best practices for generating the Hash Code see John Skeets answer here.

于 2013-10-02T07:57:05.323 回答
0

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

于 2013-10-02T07:33:09.140 回答