List<T>的排序使用Comparer<T>而不是IEquatable,为什么?

12

我写了很多对象,它们都是集合的一部分,并且需要进行排序和搜索。对于大多数对象,我已经实现并重载了Equals方法、IEquatable接口以及operator!operator==运算符。

现在我想在一个已实现所有上述功能的对象上使用List<T>.Sort,结果发现我需要实现IComparable才能进行自定义排序。

为什么Sort使用IComparable,那么在我的所有对象中实现IEquatable有什么意义呢?

另外,Object.Equal的重载与所有这些有什么关系呢?


1
想象一下,你有三个整数 abc,已知 a==ba!=cb!=c(这是所有可能的组合)。现在,请将 abc 按升序排列。 ;p - Marc Gravell
7个回答

15
它不可能使用IEquatable<T>进行排序 - 知道两个物品是否相等不能帮助您对它们进行排名。但是,如果您的类型实现了IComparable<T>或任何IComparer<T>(包括Comparer<T>.Default),则可以使用它来提供自定义比较器对象。函数式风格(Comparison<T>)也很方便,用于临时排序而不需要大量代码:
list.Sort((x,y) => string.Compare(x.Name, y.Name));

但是,如果你只需要一个简单的顺序排序,让你的T实现IComparable<T>接口,并且只需使用:

list.Sort();

7

相等性只能告诉你两个对象是否相等。它不能告诉你在排序顺序中x应该在y之前还是之后。如果仅有相等性,您将如何建议List<T>执行任何排序?

实现IEquatable<T>的目的是在重要的情况下使用相等性,例如在HashSet<T>中或作为Dictionary<TKey,TValue>中的键类型。同样,这些无法仅使用IComparable<T>有效地实现,因为它不会提供哈希码。

这两个接口基本上用于不同的情况。


4
因为 IComparable 允许确定对象是比另一个对象 "更小" 还是 "更大",而 IEquatable 则有助于找出两个对象是否 "相等"。
前者在排序中需要,因为仅知道哪些对象具有相等的值并不能帮助您将它们放入特定顺序。

4

由于排序不仅仅依赖于相等性,还依赖于相对位置。为了进行排序,您需要知道对象相对于彼此的位置。大于、小于、等于。


0

相等性告诉您两个实例是否相等。可比性告诉您如何对它们进行排序。

当您比运行时更了解类型的相等性工作方式时,可以覆盖Object.Equals的实例版本。

引用类型的相等性默认为引用相等性(相同引用是相同的对象)。

object o1 = new object();
object o2 = o1;

if(o2==o1)
{
    Console.WriteLine("These reference types are equal");
}

object o3 = new object();

if(o2 != o3)
{
    Console.WriteLine("These reference types are not equal");
}

值类型的默认相等性意味着所有成员变量都是相等的。通常应该重写值类型的Equals方法,因为您可能更清楚什么是相等。

这对比较的影响在于,比较有些依赖于相等性。为了知道什么是小于或大于,您需要知道什么是相等的。


0

嗯,正如您在关于此主题的其他问题中所看到的那样,IEquatable<T>用于检查相等性,而IComparable<T>引入了排序所需的排名。


0

使用 IEquatable 接口可以定义一个等价关系,但是对于排序,你需要一个顺序


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接