What is the difference between IComparable
and IComparer
Interfaces? Is it necessary to use this interface always with Array.Sort()
method
The IComparable interface defines a generalized type-specific comparison method that a value type or class implements to order or sort its instances. The IComparable is implemented by types whose values can be ordered or sorted. The interface requires the CompareTo method to be implemented.
The IComparer. Compare method requires a tertiary comparison. 1, 0, or -1 is returned depending on whether one value is greater than, equal to, or less than the other. The sort order (ascending or descending) can be changed by switching the logical operators in this method.
The instance's IComparable implementation is called automatically by methods such as Array. Sort and ArrayList. Sort. The implementation of the CompareTo(Object) method must return an Int32 that has one of three values, as shown in the following table.
As the name suggests, IComparable<T>
reads out I'm comparable. IComparable<T>
when defined for T
lets you compare the current instance with another instance of same type. IComparer<T>
reads out I'm a comparer, I compare. IComparer<T>
is used to compare any two instances of T
, typically outside the scope of the instances of T
.
As to what they are for can be confusing at first. From the definition it should be clear that hence IComparable<T>
(defined in the class T
itself) should be the de facto standard to provide the logic for sorting. The default Sort
on List<T>
etc relies on this. Implementing IComparer<T>
on T
doesn't help regular sorting. Subsequently, there is little value for implementing IComparable<T>
on any other class other than T
. This:
class MyClass : IComparable<T>
rarely makes sense.
On the other hand
class T : IComparable<T> { public int CompareTo(T other) { //.... } }
is how it should be done.
IComparer<T>
can be useful when you require sorting based on a custom order, but not as a general rule. For instance, in a class of Person
at some point you might require to Sort people based on their age. In that case you can do:
class Person { public int Age; } class AgeComparer : IComparer<Person> { public int Compare(Person x, Person y) { return x.Age - y.Age; } }
Now the AgeComparer
helps in sorting a list based on Age
.
var people = new Person[] { new Person { age = 23 }, new Person(){ age = 22 } }; people.Sort(p, new AgeComparer()); //person with age 22 comes first now.
Similarly IComparer<T>
on T
doesn't make sense.
class Person : IComparer<Person>
True this works, but doesn't look good to eyes and defeats logic.
Usually what you need is IComparable<T>
. Also ideally you can have only one IComparable<T>
while multiple IComparer<T>
is possible based on different criteria.
The IComparer<T>
and IComparable<T>
are exactly analogous to IEqualityComparer<T>
and IEquatable<T>
which are used for testing equality rather than comparing/sorting; a good thread here where I wrote the exact same answer :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With