Introduction
This article explains how to sort Lists by using two interfaces IComparable<>
and IComparer<>
provided by the .NET Framework.
Background
It's easy to sort a list of strings or integers by just calling the List.Sort()
method, but how can we sort two objects and based on what field?
Let's look at a small example and see how we can solve the problem using IComparable<>
and IComparer
interfaces.
Example
Let's create a simple Employee
class with two fields, Name
and Salary
.
class Employee
{
public string Name { get; set; }
public int Salary { get; set; }
}
Now create a List
of Employee
s and call Sort()
method of a List
.
List<Employee> empList = new List<Employee>()
{ new Employee { Name = "a", Salary = 14000 },
new Employee { Name = "b", Salary = 13000 }
};
empList.Sort();
Oops! we got an exception!
The Exception
says we need to implement IComparable<>
interface,
List.Sort()
sorts any class that implements IComparable<>
Interface which has one method called CompareTo()
.
Let's implement IComparable<>
interface to our Employee
class:
class Employee : IComparable<Employee>
{
public string Name { get; set; }
public int Salary { get; set; }
#region IComparable<Employee> Members
public int CompareTo( Employee other )
{
if ( this.Salary < other.Salary ) return 1;
else if ( this.Salary > other.Salary ) return -1;
else return 0;
}
#endregion
}
In the above code, we are sorting objects based on salary of employee in descending order, by implementing CompareTo()
method of IComparable
interface which takes Employee
reference as a parameter.
Now, calling empList.Sort()
gives no exception and empList
is well sorted by salary
.
But sometimes, we may need to sort a list of objects when class does not implement IComparable<>
interface and also we may need various kinds of sorting on that class like:
- Sort
Employee
s by Salary
in Ascending Order
- Sort
Employee
s by Salary
in Descending Order
- Sort
Employee
s by Name
To solve this problem, .NET provides a special interface called IComparer<>
which has a method Compare()
, takes two object parameters X
, Y
and returns an int
.
Use of IComparer<>
interface tells List
how exactly you want to sort.
class Employee_SortBySalaryByAscendingOrder : IComparer<Employee>
{
#region IComparer<Employee> Members
public int Compare( Employee x, Employee y )
{
if ( x.Salary > y.Salary ) return 1;
else if ( x.Salary < y.Salary ) return -1;
else return 0;
}
#endregion
}
class Employee_SortBySalaryByDescendingOrder : IComparer<Employee>
{
#region IComparer<Employee> Members
public int Compare( Employee x, Employee y )
{
if ( x.Salary < y.Salary ) return 1;
else if ( x.Salary > y.Salary ) return -1;
else return 0;
}
#endregion
}
class Employee_SortByName : IComparer<Employee>
{
#region IComparer<Employee> Members
public int Compare( Employee x, Employee y )
{
return string.Compare( x.Name, y.Name );
}
#endregion
}
The above code introduces three classes by implementing Compare()
method of IComparer
interface.
Now, how do we use this? We just have to pass the reference of these classes as a object parameter to Sort()
method as shown below:
List<Employee> empList = new List<Employee>()
{ new Employee { Name = "a", Salary = 14000 },
new Employee { Name = "b", Salary = 13000 }
};
Employee_SortBySalaryByAscendingOrder eAsc =
new Employee_SortBySalaryByAscendingOrder();
empList.Sort( eAsc );
Employee_SortBySalaryByDescendingOrder eDsc =
new Employee_SortBySalaryByDescendingOrder();
empList.Sort( eDsc );
Employee_SortByName eName = new Employee_SortByName();
empList.Sort( eName );
Conclusion
Sorting Lists is simple as long as you sort basic elements like strings and integers for which comparison classes are defined.
Usage of IComparable<>
and IComparer<>
interface helps to sort Lists of objects on custom classes easily.
History