C# i可比与等于()

C# i可比与等于(),c#,C#,从 实现IComparable的类型必须重写Equals。重写Equals的类型也必须重写GetHashCode;否则,哈希表可能无法正常工作 我不太明白。任何人都可以解释。IComparable是一个接口,它定义了实现类的两个实例可以被视为彼此大于、小于或等于。由于在该接口的方法中定义了相等,因此还需要重写Equals方法(和相等运算符),以确保这两个方法的结果一致 public class EqualityTest : IComparable<EqualityTest> {

实现IComparable的类型必须重写Equals。重写Equals的类型也必须重写GetHashCode;否则,哈希表可能无法正常工作


我不太明白。任何人都可以解释。

IComparable是一个接口,它定义了实现类的两个实例可以被视为彼此大于、小于或等于。由于在该接口的方法中定义了相等,因此还需要重写Equals方法(和相等运算符),以确保这两个方法的结果一致

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

      public int CompareTo(EqualityTest other)
      {
           return this.Value.CompareTo(other.Value);
      }
}
然后运行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);
    }

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

有两种方法可以比较代码中的对象:
Equals
GetHashCode

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


如果覆盖其中一个对象而不是另一个对象,则可能会得到意外的结果。

IComparable用于比较两个对象-如果认为它们相等,则Compare将返回0。如果两个对象的IComparable.Compare返回零,而obj1.Equals(obj2)返回false,这将是非常意外的,因为这意味着两个对象具有两种不同的相等含义


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

有关Equals和GetHashCode之间的关系的更多信息:还请注意,尽管在每种情况下都必须遵守IComparable、Equals和GetHashCode()的约定,但不一定要显式实现所有三个,只要取得一致的结果。主要是指具有相同哈希代码的两个对象相等,并在CompareTo()上返回0。@rushinge我认为该语句是错误的:“主要是指具有相同哈希代码的两个对象相等,在CompareTo()上返回0。”。如果对象相等,建议GetHashCode()返回相同的值,CompareTo()返回0。如果IComparable.Compare返回零,则可以轻松生成不同/不相等的实例,这些实例返回相同的哈希代码:),这是否真的意味着这些项应该被视为相等的,或者仅仅是不存在明确的有序关系?假设有一个不可变的类ScheduleEvent,其中包括DateTime类型的EventTime和MethodInvoker类型的EventAction字段。ScheduleEvent对象将具有基于EventTime的自然顺序,但我认为具有相同EventTime但不同委托的ScheduleEvent对象应该从CompareTo返回0,但从Equals返回False。在我看来,如果存在一种可能性,即一个类型通常有一个明确的排序顺序,但可能存在一组相互不等价的值,但它们之间没有自然的相对排序,那么
CompareTo()就完全合适了
返回零,但对于
Equals()
返回false(例如,我认为
Decimal
在比较
1.0m
1.00m
时应该这样做)。在我看来,
Equals
应该定义一个相对严格的相等关系,即使在
=
CompareTo
可能定义一个更宽松的相等关系的情况下。
    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);
    }