IComparable接口是否过时/“有害”?


11

IComparable 仅以一种方式工作

假设您有一Employee堂课。在一个视图中,您要显示所有Employees按名称排序的视图-在另一个视图中按地址显示。您将如何实现?不使用IComparable,至少不是以任何惯用的方式。

IComparable 逻辑错误

通过调用使用该接口.Sort()。在显示Customer按名称排序的视图中,根本没有代码暗示如何进行排序。
另一方面,Customer该类假设如何使用它-在这种情况下,它将在按名称排序的列表中使用。

IComparable 隐式使用

与替代方案相比,很难看到在何处使用了比较逻辑,或者根本看不到。假设您使用标准IDE,并从Customer课堂开始,我将不得不

  1. 搜索所有引用 Customer
  2. 查找列表中使用的那些引用
  3. 检查这些列表是否曾经拜访过.Sort()它们

更糟的是,如果删除IComparable仍在使用的实现,则不会收到任何错误或警告。您将得到的唯一一件事就是在所有难以理解的地方出现错误的行为。

这些问题加在一起,加上需求不断变化

我之所以开始考虑这一点,是因为它对我来说是错的。我已经IComparable在我的应用程序中愉快地使用了两年了。现在,需求发生了变化,事物需要以两种不同的方式进行分类。已经注意到,遍历上一节中描述的步骤并不是一件有趣的事情。

问题

这些问题使我认为IComparable不如IComparer.OrderBy(),以至于看不到任何其他替代方案无法更好地解决的有效用例。
使用IComparer或LINQ 总是更好吗,还是这里没有我看到的优点/用例?


2
您新的“以两种不同方式分类”要求是一条红鲱鱼。要解决此问题,您要做的就是将一个不同的比较器传递给您的排序函数。
罗伯特·哈维

@RobertHarvey然后,您将不再使用IComparable它,这强化了我的观点。
R. Schmitz

不要忘了,如果你使用的SortedXXX集合,他们要么需要存储的元素是IComparable或有IComparer提供。另请注意,使用一个比较器逆转自然排序顺序并使其适用于所有IComparable对象是很简单的。
Berin Loritsch

2
有两个不同的接口没关系。 IComparable被认为是默认的比较机制。 IComparer当您要覆盖默认比较机制时使用。
罗伯特·哈维

Answers:


14

IComparable有您提到的限制,那是正确的。它是.NET Framework 1.0中已经提供的接口,在该接口上这些功能替代方案和Linq不可用。所以是的,人们可能会将其视为过时的框架元素,主要是为了向后兼容而保留的。

但是,对于许多简单的数据结构,一种排序方式可能足够或自然。对于这些情况,拥有一个规范的位置来实现顺序关系仍然是使代码保持DRY的一种好方法,而不是总是在每次OrderBy对整个位置的调用中都重复相同的逻辑。

如您所写,您“已经在应用程序中愉快地使用IComparable两年了”,因此对我来说,它很长时间以来一直为您服务。现在,您必须验证,更改和测试所有对to的调用时Sort,这也可能表明您在许多地方都在执行相同的排序逻辑,这并不是的错IComparable。因此,这可能是将更多这种逻辑集中在一个地方的机会,使您的代码更加干燥。


关于简单数据结构的要点。但是,最后一段对我来说不是100%有意义的。如果我没有使用过IComparable,那么所有先前存在的排序代码都将在各自的视图中保持不变,而我只会为新视图添加新的排序代码。
R. Schmitz

@ R.Schmitz如果没有IComparable您编写的实现,现有的排序是否可以正常工作?
罗伯特·哈维

3
@ R.Schmitz:可以,但是现在您承诺始终提供一个比较器(当然,除非您使用OrderBy)。使用IComparable,您可以免费获得默认的实现,有时甚至不必编写该实现。
罗伯特·哈维

2
@ R.Schmitz:您在这里的最后一条评论很好地总结了这一点。我会走得更远。假设您的数字类型为BigInteger。如果它没有实现比较运算符/接口,那么您自己将如何实现IComparer呢?您需要访问内部数据结构才能有效地执行或根本不执行此操作。假设您有一个类似Customer的类型;你希望公共属性进行排序上有comparers。对我来说,这是不同的:IComparable<T>如果期望调用者实现比较器是不合理的,则实现。
埃里克·利珀特

1
If I hadn't used IComparable, all the pre-existing sorting code would have been left untouched in their respective views, while I'd only add new sorting code for the new view.仅仅因为IComparable是一个更好的解决方案的时候,并不意味着它是最好的解决方案今天。您在这里的第一个评论暗示“它是IComparable或什么都不是”,这是不正确的,可以用许多不同的方法解决问题。应用程序的大小/规模可能会增长,过去看起来合适的事物可能无法满足应用程序不断增长的需求。
扁平的

1

我同意你的观点 IComparable

看一下上面的评论 Array.Sort()

  • 数组的每个元素必须实现IComparable接口,以便能够与数组中的每个其他元素进行比较。(或者抛出异常)
  • 如果排序未成功完成,则结果不确定。

我们现在可能永远不会有动机,但是!考虑object.Equals()在每个对象上使用一种方法,该方法使您可以将对象彼此比较以查看它们是否“相同”

您已经在那儿了,但是已经添加了任务,Array.Sort()您可能想添加object.Compare(object)

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.