我有一个名为'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的一个子集。我错过了什么?
答案 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中,比较方法是哈希码。