Sorting Collections in C#

Posted: May 7, 2011 in .NET, C#
Tags: , , , ,

In this post we will discuss about different techniques of sorting collections of objects in C# using the functions provided by the base class libraries.This is something very common and there different types of provisions in .NET BCL to achieve the same.We will try to discuss the advantages and limitations of each of these approaches.

I will start with the most simplest of all the techniques that is implementing the interface IComparable<T>. The IComparable<T> has the following methods:

  • int CompareTo(T other) – This method compares one instance of object of type T with another which is passed as parameter.

The following class implements an IComparable<T> interface as shown below:

public class Member : IComparable<Member> 
    { 
        public int ID { get; set; } 
        public String FirstName { get; set; } 
        public String LastName { get; set; } 
        public DateTime DateOfJoining { get; set; }


        public int CompareTo(Member other) 
        { 
            return this.ID.CompareTo(other.ID); 
        } 
    }

Here the comparison is done based on the property ID of the member class. The following snippet is used to demonstrate the usage.

List<Member> ls = new List<Member>() 
                                { 
                                    new Member(){ID=1,FirstName="John",LastName="Doe"}, 
                                    new Member(){ID=3,FirstName="Allan",LastName="Jones"}, 
                                    new Member(){ID=2,FirstName="Martin",LastName="Moe"}, 
                                    new Member(){ID=4,FirstName="Ludwig",LastName="Issac"} 
                                }; 
ls.Sort(); 
ls.ForEach(m => Console.WriteLine("Member " + m.FirstName + ":" + m.LastName));

Here the output will be sorted by ID as shown below:

Member John:Doe
Member Martin:Moe
Member Allan:Jones
Member Ludwig:Issac

Now if we want to sort by other properties as well like FirstName, LastName etc. One crud approach is to create different subclasses as shown below:

public class MemberByFirstName : Member, IComparable<MemberByFirstName> 
    { 
        public int CompareTo(MemberByFirstName other) 
        { 
            return this.FirstName.CompareTo(other.FirstName); 
        } 
    }

Then when we need to sort by say FirstName we will use List of this sub class as shown below:

List<MemberByFirstName> ls = new List<MemberByFirstName>() 
{ 
            new MemberByFirstName(){ID=1,FirstName="John",LastName="Doe"}, 
            new MemberByFirstName(){ID=3,FirstName="Allan",LastName="Jones"}, 
            new MemberByFirstName(){ID=2,FirstName="Martin",LastName="Moe"}, 
            new MemberByFirstName(){ID=4,FirstName="Ludwig",LastName="Issac"} 
}; 
ls.Sort(); 
ls.ForEach(m => Console.WriteLine("Member " + m.FirstName + ":" + m.LastName));

The output will be alphabetically sorted by FirstName as shown below:

Member Allan:Jones
Member John:Doe
Member Ludwig:Issac
Member Martin:Moe

But this is a cumbersome and rigid approach.Similar stuff can be implemented in a much more cleaner way using the IComparer<T> interface.This interface defines the following method:

  • int Compare(T x,T y) – This method takes two objects of type T and compares between them.

We can implement IComparer<T> as shown below:

public class MemberSorterByLastName : IComparer<Member> 
   {

       public int Compare(Member x, Member y) 
       { 
           return x.LastName.CompareTo(y.LastName); 
       } 
   } 
   public class MemberSorterByFirstName : IComparer<Member> 
   {

       public int Compare(Member x, Member y) 
       { 
           return x.FirstName.CompareTo(y.FirstName); 
       } 
   } 
  

We can use the method Sort(IComparer comparer) as shown below to sort the List of Member by FirstName and LastName respectively:

List<Member> ls = new List<Member>() 
                                { 
                                    new Member(){ID=1,FirstName="John",LastName="Doe"}, 
                                    new Member(){ID=3,FirstName="Allan",LastName="Jones"}, 
                                    new Member(){ID=2,FirstName="Martin",LastName="Moe"}, 
                                    new Member(){ID=4,FirstName="Ludwig",LastName="Issac"} 
                                };

ls.Sort(new MemberSorterByFirstName());

ls.ForEach(m => Console.WriteLine("Member " + m.FirstName + ":" + m.LastName));

ls.Sort(new MemberSorterByLastName());

ls.ForEach(m => Console.WriteLine("Member " + m.FirstName + ":" + m.LastName));

This approach is clean but has the overhead of creating separate classes for each different sort criteria.This can be achieved much more simply using the Comparison<T> delegate. The Comparison<T> delegate has the following signature:

  • public delegate int Comparison<in T>(T x,T y) – This is used to compare two objects of generic type T.

We can use the Sort (Comparison<T> comparison) method as shown below:

List<Member> ls = new List<Member>() 
                    { 
                        new Member(){ID=1,FirstName="John",LastName="Doe"}, 
                        new Member(){ID=3,FirstName="Allan",LastName="Jones"}, 
                        new Member(){ID=2,FirstName="Martin",LastName="Moe"}, 
                        new Member(){ID=4,FirstName="Ludwig",LastName="Issac"} 
                    };

ls.Sort((x, y) => x.FirstName.CompareTo(y.FirstName)); 
ls.ForEach(m => Console.WriteLine("Member " + m.FirstName + ":" + m.LastName));

ls.Sort((x, y) => x.LastName.CompareTo(y.LastName)); 
ls.ForEach(m => Console.WriteLine("Member " + m.FirstName + ":" + m.LastName)); 

By far this approach is the most simplest one. In other languages like Java the first two options are there e.g. Java Comparer interface is similar to IComparable and Comparator interface is similar to IComparer in C# respectively. But Java is yet to have support for Closures so the third approach is still not possible.

About these ads
Comments
  1. Sorting Collections in C# « Sankarsan’s Journal…

    Thank you for submitting this cool story – Trackback from DotNetShoutout…

  2. […] Sorting Collections in C# – Sankarsan’s […]

  3. Soavn bera says:

    enthusiastic article.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s