我知道在实现自定义相等性检查时覆盖GetHashCode的重要性-为此,我已经实现了IEquality<T>接口(interface),以及通用和非通用Equals的区别as discussed here.现在是否有覆盖Equals(object t)的要点?难道不是所有的东西都在通用Equals(T t)下吗?

public override int GetHashCode() //required for hashsets and dictionaries
{
    return Id;
}

public bool Equals(T other) //IEquatable<T> here
{
    return Id == other.Id;
}

public override bool Equals(object obj) //required??
{
    return Equals(obj as T);
}

最佳答案

未密封的类型不应实现IEquatable<T>,因为确保(甚至使其可能)派生类型正确实现它的唯一方法是实现IEquatable<T>.Equals(T)以便调用Object.Equals(Object)。由于IEquatable<T>的全部目的是避免在比较之前将CPU转换为Object所浪费的CPU时间,因此调用Object.Equals(Object)的实现无法比没有实现该接口(interface)时所实现的默认行为更快地进行操作。

密封的类类型可以通过实现IEquatable<T>获得一点性能优势;首选的样式是让Object.Equals(Object)尝试将参数转换为T;如果强制转换成功,请使用IEquatable<T>.Equals实现;否则返回false。传递相同的对象实例时,IEquatable.Equals(T)Object.Equals(Object)在任何情况下都不会产生不同的结果。

结构类型可以使用与密封类类型相同的模式。尝试强制类型转换的方法略有不同,因为失败的强制类型转换不能返回null,但是模式应该仍然相同。如果一个结构实现了一个变异接口(interface)(例如List<T>.Enumerator,一个实现IEnumerator<T>的结构),那么相等比较的正确行为就有点模糊了。

顺便说一句,应将IComparable<T>IEquatable<T>视为彼此独立。虽然在X.CompareTo(Y)为零时通常会发生这种情况,但X.Equals(Y)会返回true,但某些类型可能具有自然的顺序,其中两种情况可能会有所不同,而另一种情况不会彼此排名。例如,可能有一种NamedThing<T>类型,它结合了stringT。这种类型将支持名称的自然排序,但不一定支持T。名称匹配但T不同的两个实例应为0返回CompareTo,但对于false返回Equals。因此,如果未更改IComparable,则覆盖GetHashCode不需要覆盖Equals

关于c# - 如果我正在实现IEquatable <T>,则覆盖Equals是否重要?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13741737/

10-16 02:14