IComparable和IEquatable接口之间有什么区别?


Answers:


188

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

IComparable 对要比较的对象施加总排序。

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



10

除了格雷格D的答案:

您可能IComparable没有实现IEquatable对部分排序有意义的类,而您确实希望消费者推断出仅仅因为CompareTo()返回零,这并不意味着对象相等(除了排序目的以外),这可能不会实现


10
这听起来更像是一种特殊情况的比较器,而不是像一个实现IComparable正确的对象。你能想出一个有意义的例子,其中CompareTo(…) == 0没有暗示平等?我当然不能。实际上,接口协定(按照MSDN)要求CompareTo(…) == 0意味着平等。说穿了,在这样的情况下你的,使用一种特殊的Comparator对象,也没有实现IComparable
康拉德·鲁道夫

2
@Konrad-我确实指出了一些警告-类型没有实现IEquatable(显然,发起者不希望包括相等性测试),并且CompareTo结果用于排序而不是评估相等性。您还会遇到与平等相关的问题(引用,值,忽略“任意”属性-长度为500页的蓝皮书可能等同于长度为500页的红皮书,就IComparable而言)
Damien_The_Unbeliever

4
您的最后一句话是错误的,这是我要指出的特殊错误:IComparable在这里完全不合适。您所拥有的是非常特殊的顺序,仅适用于一种特殊情况。在这种情况下,实施将军IComparable是错误的。这就是IComparer那里的目的。例如,人们不能被有意义地命令。但是可以根据他们的薪水,鞋子的大小,雀斑的数量或重量来订购。因此,我们将为IComparer所有这些情况实现不同的。
康拉德·鲁道夫

2
@Konrad Rudolph:诸如“ ScheduledEvent”类之类的东西应该在特定时间执行“某事”吗?该类型的语义将暗示一种非常强的自然语义排序,该自然语义排序基于应该在何时执行该操作,但是很容易同时发生不同的事件。可能需要使用手动指定的IComparer,但我平均认为在类中内置比较器会更方便。
supercat

4
@supercat便利性很重要,但这还不是全部。正确性(如逻辑一致性)更为重要,而静态类型系统是验证此逻辑一致性的重要工具。通过违反实现的接口文档记录,您正在破坏类型系统。这不是一个好主意,我永远不会推荐它。在这种情况下,请使用外部比较器。
Konrad Rudolph

7

IEquatableMSDN页面上所述:

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

EqualsCompareTo


2

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 };

可以对这些对象进行排序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);
        }
    }
}

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


接下来比较两个对象可以使用Equals()method。

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

这将返回,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;
        }
    }
}

1
感谢您的出色解释。问:为什么IEquatable使用一个通用的<Person>IComparable不?
veuncent
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.