IComparable和Equals()

dev*_*ull 8 c#

来自MSDN

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

我没理得.谁能解释一下.

Mar*_*ris 11

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

public class EqualityTest : IComparable<EqualityTest>
{
      public int Value { get; set; }

      public int CompareTo(EqualityTest other)
      {
           return this.Value.CompareTo(other.Value);
      }
}
Run Code Online (Sandbox Code Playgroud)

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

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


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

public class EqualityTest
{
     public string A { get; set; }
     public string B { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

并运行了Resharper有用的"生成平等"功能,说我希望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);
    }
Run Code Online (Sandbox Code Playgroud)

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