C# Sorting – Is the IComparable Interface Outdated or Harmful?

ccomparisonsorting

IComparable only works one way

Let's say you have a Employee class. In one view, you want to show all Employees sorted by name – in another, by address. How are you going to achieve that? Not with IComparable, at least not in any idiomatic way.

IComparable has the logic in the wrong place

The interface is used by calling .Sort(). In a view showing Customer sorted by name, there is no code at all to implicate how it is going to be sorted.
On the other hand, the Customer class is assuming how it is going to be used – in this case, that it will be used in a list sorted by names.

IComparable is used implicitly

In comparison with the alternatives, it is very difficult to see where the comparing logic is being used – or if at all. Assuming your standard IDE and starting from the Customer class, I will have to

  1. Search for all references to Customer
  2. Find those references which are used in a list
  3. Check if those lists ever have .Sort() called on them

What's probably worse, if you remove an IComparable implementation that is still being used, you get no error or warning. The only thing you will get is wrong behaviour in all places that were too obscure for you to think of.

These issues combined, plus changing requirements

The very reason I came to think about this is because it went wrong for me. I have been happily using IComparable in my application for 2 years now. Now, the requirements changed and the thing needs to be sorted in 2 different ways. It have noticed that it is no fun going through the steps described in the previous section.

The question

These issues make me think of IComparable as inferior to IComparer or .OrderBy(), to the point of not seeing any valid use case that wouldn't be served better by the alternatives.
Is it always better to use IComparer or LINQ, or are there advantages/use cases I am not seeing here?

Best Answer

IComparable has the restrictions you mentioned, that is correct. It is an interface which was already available in .NET framework 1.0, where those functional alternatives and Linq were not available. So yes, one might see it as an outdated framework element which is mainly kept for backwards compatibility.

However, for lots of simple data structures, one way of sorting is probably enough or natural. For these cases, having one canonical place to implement the order relationship is still a good way to keep the code DRY, instead of always repeating the same logic in every call to OrderBy all over the place.

You have been "happily using IComparable in your application for 2 years now", as you wrote, so it appears to me it served you well for a long time. When you now have to validate, change and test all calls to Sort, it may also be a sign you were doing the same kind of sorting logic in many places, which is not the fault of IComparable. So this could be an occasion to centralize more of this logic in one place, making your code more DRY.