IComparable和IEquatable接口有什么区别?

Sof*_*eek 90 c# interface icomparable iequatable

这两个接口似乎都在比较对象是否相等,那么它们之间的主要区别是什么?

Gre*_*g D 180

IEquatable 测试两个对象是否相等.

IComparable 对被比较的对象施加总排序.

例如,IEquatable会告诉你5不等于7. IComparable会告诉你5在7之前.


Isl*_*ene 15

IEquatable<T> 为了平等.

IComparable<T> 订购.


Dam*_*ver 10

除了Greg D的回答:

您可以实现IComparable而不为部分排序有意义的类实现IEquatable,并且非常肯定您希望消费者绘制推理,因为CompareTo()返回零,这并不意味着对象是相等的(对于任何事情)除了分类目的).

  • 这听起来更像是一个特殊情况的比较器,而不是像正确实现"IComparable"的对象.你能想出一个有意义的例子,其中`CompareTo(...)== 0`不**意味着平等吗?我当然不能.事实上,接口契约(根据MSDN)**要求**"CompareTo(...)== 0"意味着相等.说白了,在你的情况下,使用一个特殊的`Comparator`对象,不要*实现`IComparable`. (10认同)
  • 你的最后一句话是错的,这是我想指出的特殊错误:"IComparable"在这里完全不合适.你得到的是一个非常特殊的*订单,只适用于一种特殊情况.对于这种情况,实现一般的"IComparable"是错误的.这就是IComparer的用武之地.例如,人们不能有意义地订购.但他们*可以根据他们的工资,鞋子大小,雀斑数量或体重来订购.因此,我们将为所有这些情况实现不同的"IComparer". (4认同)
  • @supercat便利很重要,但并不是一切.正确性(如逻辑一致性)更重要,静态类型系统是验证逻辑一致性的重要工具.通过违反您实现的已记录的接口合同,您将颠覆类型系统.这不是一个好主意,我永远不会推荐它.在这种情况下使用外部比较器. (3认同)
  • @Konrad - 我确实指出了几个警告 - 该类型没有实现IEquatable(显然,发起者不希望包含相等测试),并且CompareTo结果用于排序,*不*用于评估相等性.您还会遇到与相关性相关的问题(参考,价值,忽略"任意"属性 - 为了IComparable的目的,长度为500页的蓝皮书可能与500页长度的红皮书"相等") (2认同)
  • @Konrad Rudolph:像"ScheduledEvent"类这样的东西,应该在某个特定时间做"某事"?该类型的语义意味着基于该动作何时发生的非常强的自然语义排序,但是可以容易地同时发生不同的事件.人们可能需要使用手动指定的IComparer,但我希望在类中内置比较器会更方便. (2认同)

Wil*_*ins 6

IEquatableMSDN页面所述:

IComparable接口定义CompareTo方法,该方法确定实现类型实例的排序顺序.IEquatable接口定义了该Equals方法,该方法确定实现类型的实例的相等性.

EqualsCompareTo


Nip*_*una 5

IComparable <T> 定义了一种特定于类型的比较方法,可用于对对象进行排序或排序。

IEquatable <T> 定义了可用于实现确定相等性的通用方法。


假设你有 Person 类

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

Person p1 = new Person() { Name = "Person 1", Age = 34 };
Person p2 = new Person() { Name = "Person 2", Age = 31 };
Person p3 = new Person() { Name = "Person 3", Age = 33 };
Person p4 = new Person() { Name = "Person 4", Age = 26 };

List<Person> people = new List<Person> { p1, p2, p3, p4 };
Run Code Online (Sandbox Code Playgroud)

要对这些对象进行排序,您可以使用people.Sort();.

但这会抛出异常。

在此处输入图片说明

框架不知道如何对这些对象进行排序。您需要告诉如何对实现IComparable接口进行排序。

public class Person : IComparable
{
    public string Name { get; set; }
    public int Age { get; set; }

    public int CompareTo(object obj)
    {
        Person otherPerson = obj as Person;
        if (otherPerson == null)
        {
            throw new ArgumentNullException();
        }
        else
        {
            return Age.CompareTo(otherPerson.Age);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这将使用Sort()方法对数组进行正确排序。


接下来比较两个对象,您可以使用Equals()方法。

var newPerson = new Person() { Name = "Person 1", Age = 34 };
var newPersonIsPerson1 = newPerson.Equals(p1);
Run Code Online (Sandbox Code Playgroud)

这将返回,false因为Equals方法不知道如何比较两个对象。因此,您需要实现IEquatable接口并告诉框架如何进行比较。扩展上一个示例,它看起来像这样。

public class Person : IComparable, IEquatable<Person>
{
    //Some code hidden

    public bool Equals(Person other)
    {
        if (Age == other.Age && Name == other.Name)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)