Monday, December 3, 2012

A Comparison of IComparable and IComparer interfaces in C#




.Net framework provides 2 interfaces (IComparable and IComparer) for purpose of sorting/Comparing . 

IComparable <T>:

This interface is to be implemented by the class itself whose instances need ordering/sorting .It provides CompareTo method to implement.
All .net primitive types like Int32,String etc. implements IComparable.So we can easily compare 2 built in types using CompareTo method.
Eg.
  int i = 9;
  int j=10;
  i.CompareTo(j);
Also if we have a collection of a built in type we can sort the collection easily.

Eg.
List<int> lstInt = new List<int>();
lstInt.Sort();

Now say we have a custom type Employee. Lets try the following
 List< Employee > lstEmp = new List< Employee >();
…………………………………….
Add some employees
…………………………………
lstEmp.Sort();

Now when we try to do sorting on a custom type we will get exception “Failed to compare two elements in the array.”
It is because to use sort() on anytype , the type has to implement IComparable .Now lets try by implementing IComparable .
e.g.
  public class Employee:IComparable<Employee>
    {
        public string Name { get; set; }
        public int JanSalary {get;set; }
        public int FebSalary { get; set; }

       
        #region IComparable<Employee> Members

        public int CompareTo(Employee other)
        {
            return this.Name.CompareTo(other.Name);
        }

        #endregion
    }

public class Comparison1
  {
      List<Employee> lstemp = new List<Employee>();
      public void docomparison()
      {

          Employee emp1 = new Employee();
          emp1.Name = "satya";
          emp1.JanSalary = 2000;
          Employee emp2 = new Employee();
          emp2.Name = "biswa";
          emp2.JanSalary = 300;
          Employee emp3 = new Employee();
          emp3.Name = "parsottam";
          emp3.JanSalary = 1000;
          Employee emp4 = new Employee();
          emp4.Name = "kalyani";
          emp4.JanSalary = 15000;
          EmpJanSalComparer cc = new EmpJanSalComparer();
          lstemp.Add(emp1);
          lstemp.Add(emp2);
          lstemp.Add(emp3);
          lstemp.Add(emp4);
          lstemp.Sort();

      }
  }

Here when we try to sort the list , CompareTo method will be called in Employee class and sorting/ordering can be performed.
We can use LINQ for the same . In that case we don’t have to implement IComparable in “Employee” class.

lstemp.Sort((x,y)=>x.Name.CompareTo(y.Name));

As we have to use IComparable with the class which needs comparison(Employee in above case) , we are restricted to do one type of comparison / ordering only(in this case on basis of property “Name“).

Suppose I need comparison on basis of “JanSalary” then I can’t do it now with IComparable .



IComparer<T> :

For these scenarios we have “IComparer<T>” interface using which we can have our custom comparisons. IComparer is used with a separate class as shown below.
public class EmpJanSalComparer : IComparer<Employee>
    {
        #region IComparer<Employee> Members

        public int Compare(Employee x, Employee y)
        {
            if (x.JanSalary > y.JanSalary)
            {
                return 1;
            }
            else if (x.JanSalary < y.JanSalary)
                return -1;
            else
                return 0;
        }

        #endregion
    }

    public class EmpFebSalComparer : IComparer<Employee>
    {
        #region IComparer<Employee> Members

        public int Compare(Employee x, Employee y)
        {
            if (x.FebSalary > y.FebSalary)
            {
                return 1;
            }
            else if (x.FebSalary < y.FebSalary)
                return -1;
            else
                return 0;
        }

        #endregion
    }


So as we see   it has a method “Compare” which takes 2  parameters of type “T” .And it is used with a separate class and we can use many of these classes as needed. So it gives flexibility/extendibility in terms of comparison/sorting.
Here for comparing jan month salary we used  EmpJanSalComparer” class and for comparing feb month salary we used “EmpFebSalComparer .We can use these comparer for sorting as shown below.
  EmpJanSalComparer cc = new EmpJanSalComparer();
  lstemp.Add(emp1);
  lstemp.Add(emp2);
  lstemp.Add(emp3);
  lstemp.Add(emp4);
  lstemp.Sort(cc);

Hope you enjoyed the article. Please leave a honest comment/feedback.