IComparable & IComparer
In most cases, comparing two instances of the same time is considered to be an intrinsic feature of the type, through the implementation of the IComparable
interface. This is true for int
or DateTime
. But what about a Person
? Should we compare the Name
or the DateOfBirth
?
This is when the Comparer becomes handy. You can create a Comparer on your type for each scenario.
Also, comparers are presumably used to sort collections and, as they may have lots of elements, they should be very fast. The interface is so simple that it is easier to create new types than to add parameters in your instances. Also, by doing so, it makes a comparer type invariant once created and therefore it is usable in a multi-threaded fashion.
Let say that you want to be able to sort in both ascending and descending direction. If you add a SortDirection parameter in your constructor. Not only it is tempting add the SortDirection property with setters and getters, leading to potential missused, but also you add an if statement in the Compare function, that could pontentially be used millions of time.
As state, the interface is very simple, with only one method: int Compare(T x, T y)
. So you can easily make generic comparers, such as:
ReverseComparer
, that decorates aIComparer
and compare y and x, instead of x and y.CascadingComparer
, that uses anIComparer
list that, while a Comparer returns 0, compare the values with the next Comparer in the list.