SIGN UP MEMBER LOGIN:    
ARTICLE

Designing Sortable Collections using IComparable

Posted by Mahesh Chand Articles | C# Language November 21, 2005
If you are dealing with collection of objects, there are times when you need to sort the object collection. In this article, I will discuss how to use IComparable interface to design sortable arrays.
Reader Level:
Download Files:
 

.NET Framework Class Library  provides several interfaces to support additional functionality in collections such as ICollection, IList, and IComparable.

Implementing IComparable

IComparable interface is used to support the sorting in collections. It has one method - CompareTo. When you are desiging sortable objects, you must implement CompareTo method of IComparable.

For example, I create a Developer class, which is inherited from IComparable.

  
public
class Developer : IComparable
{
}


Now I implement CompareTo method like following:

  
public
int CompareTo(object obj)
{
// Some code here
}


Now let's say, Developer class has a property called ID and you want your items to be sorted on ID, we simply add the following code:

  
public
int CompareTo(object obj)
{
      if( !(obj is Developer) )
            throw new InvalidCastException("Not a valid Developer object.");
      Developer developer = (Developer)obj; 
            
return this.ID.CompareTo(developer.ID);
}


As you can see from the above code, it basically compares the current value of the object with the new value.

Now let's say, the Developer object has public properties called - FirstName, LastName, Age, and Experience and you want the sorting can be done based on any of these properties.

To do so, I defined an enumeration:

  
public
enum SortFilter
{
      FirstName,
      LastName,
      Age,
      Experience
}

After that, I add a static property to the Developer class of type SortFilter:

  
private
static SortFilter sortingBy = SortFilter.FirstName;
public static SortFilter SortingBy
{
      get { return sortingBy; }
      set { sortingBy = value; }
}

Now I change the CompareTo method to the following:

  
public
int CompareTo(object obj)
{
      if( !(obj is Developer) )
            throw new InvalidCastException("Not a valid Developer object.");
      Developer developer = (Developer)obj; 
      switch(Developer.SortingBy)
      {
             case SortFilter.FirstName: 
                   
return this.FirstName.CompareTo(developer.FirstName);
        case SortFilter.LastName: 
                   return this.LastName.CompareTo(developer.LastName);
        case SortFilter.Age: 
            return this.Age.CompareTo(developer.Age);
        case SortFilter.Experience:
            return this.Experience.CompareTo(developer.Experience);
        default:
                  goto case SortFilter.FirstName;
      }
}


As you can see from the above code, I have a case statement for each filter. Now my class is ready to support sorting. All I have to do is, create an ArrayList of Developer objects, set the sorting filter, and call Sort method.

The following code creates an ArrayList of Developer objects.

  
private
ArrayList GetList()
{
      ArrayList list = new ArrayList();
      list.Add(new Developer("Mahesh", "Chand", 30, "C#,ASP.NET,Windows Forms", 10)) ; 
      list.Add(new Developer("Michael", "Gold", 35, "GDI+, ASP.NET", 15)) ; 
      list.Add(new Developer("Bhasker", "Das", 26, "VB.NET, Web Applications", 4)) ; 
      list.Add(new Developer("Ashish", "Singhal", 24, "ADO.NET, GDI+", 4)) ; 
      list.Add(new Developer("Neel", "Beniwal", 3, "C#,ASP.NET,Windows Forms", 0)) ; 
      list.Add(new Developer("Melanie", "Talmadge", 25, "Java", 2)) ; 
      return list;
}

The following code sets the SortingBy filter as "FirstName" and calls the Sort method of ArrayList. Now ArrayList will return sorted results.

 

ArrayList list = GetList();

Developer.SortingBy = (SortFilter)Enum.Parse(typeof(SortFilter), "FirstName");

list.Sort();

Sorting Order

Now you may also want to add sorting order feature  (ascending or descending) to your object. To support this, I add a SortOrder enumeartion:

 

public enum SortOrder
{
      Ascending,
    Descending
}


I also add SortingOrder static property to the Developer class as following:

  
private
static SortOrder sortingOrder = SortOrder.Ascending;
public static SortOrder SortingOrder
{
      get { return sortingOrder; }
      set { sortingOrder = value; }
}


I change the CompareTo method as following. As you can see from this method, now I am checking if SortingOrder is Ascending or Descending and based on that I am comparing the values.

 

public int CompareTo(object obj)
{
      if( !(obj is Developer) )
            throw new InvalidCastException("Not a valid Developer object."); 
      Developer developer = (Developer)obj; 
      switch(Developer.SortingBy)
      {
            case SortFilter.FirstName: 
                  if (Developer.sortingOrder == SortOrder.Ascending)
                      return this.FirstName.CompareTo(developer.FirstName);
                  else return developer.FirstName.CompareTo(this.FirstName);
            case SortFilter.LastName: 
                  if (Developer.sortingOrder == SortOrder.Ascending)
                        return this.LastName.CompareTo(developer.LastName);
                  else return developer.LastName.CompareTo(this.LastName);
            case SortFilter.Age: 
                  if (Developer.sortingOrder == SortOrder.Ascending)
                        return this.Age.CompareTo(developer.Age);
                  else return developer.Age.CompareTo(this.Age);
            case SortFilter.Experience:
                  if (Developer.sortingOrder == SortOrder.Ascending)
                        return this.Experience.CompareTo(developer.Experience);
                  else return developer.Experience.CompareTo(this.Experience);
            default:
                  goto case SortFilter.FirstName;
      }
}


Now only thing I have to do is, set the SortingOrder property of Developer object and call Sort method. That should do it. See the attached source code for more details.

  

Developer.SortingOrder = (SortOrder)Enum.Parse(typeof(SortOrder), "Descending");

list.Sort();


Summary

In this article, I discussed how to use IComparable interface to design a collection of sortable objects. 

Login to add your contents and source code to this article
share this article :
post comment
 

Sunil,
This article is sorting a collection of Developer class objects, which is a custom collection, not an array list.

Posted by Mahesh Chand Nov 30, 2005

Hi mahesh,

We want to sort model collections ( custom data transfer objects) instead of ArrayLists. Since this not a C#.NET collection but a custom collection it doesn't have Sort() method. So how do we go about sorting such a model collection ?

 

 

Posted by sunil Nov 30, 2005
Team Foundation Server Hosting
Become a Sponsor
PREMIUM SPONSORS
  • The leading .NET charting control now features PDF, Flash and Silverlight export, visualization of large datasets and more. Deliver true charting functionality to your BI, Scorecard, Presentation or Scientific apps. Download evaluation now.
    Get 2 Months Free of ASP.NET Hosting for Only $4.95/month! Receive FREE MS SQL and MySQL Databases Including ASP.NET 4/3.5, MVC 3.0, Silverlight 4, Windows 2008/IIS 7.0 Plus FREE IIS 7 Modules. Host UNLIMITED ASP.NET Web Sites - Click Here!
Team Foundation Server Hosting
Become a Sponsor