What is the difference between IComparable
and IComparer
Interfaces? Is it necessary to use this interface always with Array.Sort()
method

- 153,850
- 22
- 249
- 325

- 641
- 1
- 6
- 3
-
4**Did you [check](http://msdn.microsoft.com/en-us/library/system.icomparable.aspx) the [documentation](http://msdn.microsoft.com/en-us/library/system.collections.icomparer.aspx)?** – Cody Gray - on strike May 12 '11 at 15:54
-
3An IComparable is an object that's comparable without using an IComparer. Simple simple. ;) – jalf May 12 '11 at 18:24
6 Answers
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 :)
-
3thank you for your answer. i have a question: "class MyClass : IComparable
rarely makes sense." Why not - what's wrong with it? – BenKoshy Feb 05 '16 at 01:03 -
2@BKSpurgeon because `IComparable
` is meant for providing *default* order for instances of `T`. Not only that's what is meaningful from the very name `IComparable`, it is what is obvious from the definition of `CompareTo` method on `IComparable`s. The definition is `public int CompareTo(T)`, so that you can do `jon.CompareTo(mark)`, jon & mark being of course people. When u write, `class RandomClass : IComparable – nawfal Feb 05 '16 at 06:15`, ur `CompareTo` make code look like `refrigerator.CompareTo(parrot)`. While technically you might need this somewhere, the .NET world doesn't go about it like that. -
1@BKSpurgeon It would be confusing for .NET developers, that being not the norm. In cases you need that you can just have a static method (may be an extension method) in an appropriate class which says `public int Compare(Refrigerator r, Parrot p)` – nawfal Feb 05 '16 at 06:25
-
I don't think so it will work -people.Sort(p, new AgeComparer()); instead Array.Sort(people ,new AgeComparer()) – ni3.net May 29 '16 at 04:23
- IComparable - Defines an interface for an object with a CompareTo() method that takes another object of the same type and compares the current object to the passed one. It internalizes the comparison to the object, allowing for a more inline comparison operation, and is useful when there's only one logical way, or an overwhelmingly common default way, to compare objects of a type.
- IComparer - Defines an interface with a Compare() method that takes two objects of another type (which don't have to implement IComparable) and compares them. This externalizes the comparison, and is useful when there are many feasible ways to compare two objects of a type, or when the type doesn't implement IComparable (or the IComparable implementation compares a different way than what you want) and you don't have control over that type's source.

- 27,363
- 32
- 109
- 125

- 70,210
- 21
- 112
- 164
-
See the Visual Studio Magazine article [Multilevel Sorting with IComparable and IComparer](https://visualstudiomagazine.com/articles/2011/10/01/multilevel-sorting-with-icomparable-and-icomparer.aspx) for detailed examples. – lauxjpn Dec 09 '19 at 19:48
The best explanation I've read is "The object to be sorted will implement IComparable while the class that is going to sort the objects will implement IComparer." (source)
If the objects you're trying to sort do not implement IComparable, you'll need to create a class that implements IComparer (and accepts those object types for comparison) and pass it to the Array.Sort() method.

- 21,989
- 3
- 55
- 63
IComparable is used to provide a default sort order for your objects.
IComparer is to provide additional comparison mechanisms.
see this article for reference. http://support.microsoft.com/kb/320727

- 977
- 4
- 19
- 37
IComparer compares two objects that it's given. IComparable is implemented by the object that is being compared, for the purpose of comparing with another one of itself.
It is a good idea to implement IComparable for sorting objects. IComparable can be useful for sorting by different criteria (for example, sorting by a selectable field in the object).

- 1
- 1

- 2,062
- 1
- 18
- 19
Objects that are instances of classes that implement IComparable
can be compared to other objects. (Read IComparable
as "I can be compared.") The method on this interface that does this is CompareTo
. This is useful if you want instances of such classes to know how to compare themselves to other objects.
Objects that are instances of classes that implement IComparer
can be used to compare pairs of objects. (Read IComparer
as "I can compare.") The method on this interface that does this is Compare
. This is useful if you want to decouple the comparison logic from the class of objects being compared. One case where you might use this if you have various ways of comparing objects (this case-insensitive versus case-sensitive string comparisons).

- 236,483
- 35
- 423
- 525