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 Employees 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
Employees by Salary in Ascending Order
- Sort
Employees by Salary in Descending Order
- Sort
Employees 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