IComparable和Equals()

来自MSDN

实现IComparable的类型必须覆盖Equals.Types,覆盖Equals也必须覆盖GetHashCode; 否则,Hashtable可能无法正常工作。

我不是很明白。 谁能解释一下。

IComparable是一个接口,它定义实现类的两个实例可以看作彼此大于,小于或等于。 由于您已在该接口的方法中定义了相等性,因此还需要覆盖Equals方法(和相等运算符)以确保两者的结果一致。

public class EqualityTest : IComparable { public int Value { get; set; } public int CompareTo(EqualityTest other) { return this.Value.CompareTo(other.Value); } } 

在上面的例子中,我实现了IComparable,但没有重写Equals。 如果您使用具有相同值的类的两个单独实例调用CompareTo,则它将表示相等。 如果你用相同的两个实例调用Equals,它会说它们相等,因为它会测试它们是否是同一个对象(Equals的默认实现)。

两个相等的项应该返回相同的哈希码(用于快速查找用作哈希表中的键的项),因此如果您重写Equals,那么您还应该重写GetHashCode()


作为一个例子,我在IDE中创建了以下类:

 public class EqualityTest { public string A { get; set; } public string B { get; set; } } 

并运行了Resharper有用的“生成平等”function,说我希望A和B都能影响平等。 这是它创建的代码:

  public bool Equals(EqualityTest other) { if (ReferenceEquals(null, other)) { return false; } if (ReferenceEquals(this, other)) { return true; } return Equals(other.A, A) && Equals(other.B, B); } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) { return false; } if (ReferenceEquals(this, obj)) { return true; } if (obj.GetType() != typeof(EqualityTest)) { return false; } return Equals((EqualityTest)obj); } public override int GetHashCode() { unchecked { return ((A != null ? A.GetHashCode() : 0)*397) ^ (B != null ? B.GetHashCode() : 0); } } public static bool operator ==(EqualityTest left, EqualityTest right) { return Equals(left, right); } public static bool operator !=(EqualityTest left, EqualityTest right) { return !Equals(left, right); } 

因此,如果您重写Equals,那么您还应该定义上述所有内容以确保一致性,如果您正在实现IComparable,则同样适用。

IComparable用于比较两个对象 – 如果这些对象被认为是相等的,那么Compare将返回0.如果IComparable.Compare为两个对象返回零,那么这将是非常意外的,但obj1.Equals(obj2)返回false,因为这意味着两个不同的含义对象的相等性。

当一个类重写Equals时,它也应该重写GetHashCode,因为两个相等的对象应该散列到相同的值,并且此散列应该基于相等实现中使用的字段/属性。

可以通过两种方式比较代码中的对象: EqualsGetHashCode

为了在所有情况下正确比较您的对象,当您重写Equals方法(用于某些比较)时,您还必须覆盖GetHashCode (在其余部分中使用)。

如果您覆盖一个而不是另一个,则根据您的代码,您可能会得到意外的结果。