Alex Mueller on Software and Technology 
Wednesday, October 12, 2005

These two interfaces are often confused because of their similarity in names. However, each provides a means to sort and compare objects, but using a different approach.

I came across a need for comparing objects when using the ArrayList's Sort() method. Having used this before, I knew I needed it, but this time I needed more than just the default functionality of sorting strings. I needed to sort UDC's (User Defined Classes) on a given attribute. ArrayList's Sort() method requires that all objects being sorted either implement the IComparable interface or reference a class implementing IComparer.

The objective of this entry is to describe some differences between two interfaces, IComparer and IComparable, and to provide code showing how to use each. I find code examples helpful when I search for topics on the internet.

IComparer Interface

The IComparer interface exposes a method that compares two objects. When using a class that implements IComparable, we are overriding the default comparing method defined by the object's CompareTo() method. The object being compared does not need to implement the code to compare itself, this is done using the class that implements IComparer. Depending on what needs to be compared, multiple classes implementing IComparer can be created.

IComparable Interface

The IComparable interface when implemented provides the means to define a default comparison functionality for a given object. Only one CompareTo() method can be defined for an object. This puts some limitations on our object.

The following code examples will use fictional objects. Assume the following ArrayList.

ArrayList list = new ArrayList();
list.Add("Counting Crowes");
list.Add("Whitesnake");
list.Add("Ben Folds");
list.Add("Phish");
list.Add("ACDC");
list.Add("Led Zeppelin");

If we were to print out the list, we would see each band name displayed in the order in which it was added. It is currently not sorted.

OUTPUT
Counting Crowes
Whitesnake
Ben Folds
Phish
ACDC
Led Zeppelin

If we sort the list, we expect the results to be in alphabetical order.

list.Sort();

OUTPUT
ACDC
Ben Folds
Counting Crowes
Led Zeppelin
Phish
Whitesnake

The opposite of list.Sort() is list.Reverse(); If we wanted to sort from Z to A, we could use ArrayList.Reverse().

This is fairly strait-forward and useful, until we have classes that need to be sorted. An ArrayList of objects will not sort unless the objects themselves implement the IComparable interface, or we pass a class that implements IComparer.

To demonstrate using IComparer and IComparable, I have created a fictional class, “Album.”

class Album
{
    string artist;
    string genre;
    string title;
    string year;
    ... more code here ...
}

I can have an ArrayList of Album objects, but I still need to sort them. Let's agree to sort them on the "Artist" name. We now create a class that implements IComparer, and provide the logic to sort on the class's Artist attribute. Once the class is created, we can pass a reference to the class to the ArrayList.Sort() method.

class AlbumArtistComparer : System.Collections.IComparer
{
    // IComparer Members
    public int Compare(object x, object y)
    {    
        Album albumX = (Album)x;
        Album albumY = (Album)y;
        return albumX.Artist.CompareTo( albumY.Artist );
    }
}

My AlbumArtistComparer class implements the IComparer interface. As developers, we still need to write the logic to compare the objects. The AlbumArtistComparer class is specific to my Album class since it instantiates Album objects. To convey this to other users, I try to use class names that illustrate the objects they use. In this class, I am comparing the first object's Artist name to the second object's Artist name using the CompareTo() method built into the string class.

Assume the following ArrayList.

Album album1 = new Album("Counting Crowes", "Modern Rock", "Hard Candy", "2002");
Album album2 = new Album("Whitesnake", "80's Rock", "Greatest Hits", "1985");
Album album3 = new Album("Ben Folds", "Piano Rock", "Army", "1999");
Album album4 = new Album("Phish", "Jam Bands", "Hoist", "1994");
Album album5 = new Album("ACDC", "Hard Rock", "Powerage", "1978");
Album album6 = new Album("Led Zeppelin", "Classic Rock", "Coda", "1982");

ArrayList albumList = new ArrayList();
albumList.Add(album1);
albumList.Add(album2);
albumList.Add(album3);
albumList.Add(album4);
albumList.Add(album5);
albumList.Add(album6);

Using albumList.Sort() will throw an exception. At least one object must implement the IComparable interface. In order to sort our Album objects, we need to use the overloaded ArrayList.Sort(IComparer comparer).

albumList.Sort( new AlbumArtistComparer() );

When displayed, we now have our Album objects sorted in alphabetical order in the ArrayList. If we want to sort on the Album's "Genre" attribute, we need to create another class implementing IComparer, and pass a reference of it to the ArrayList's Sort(IComparer comparer) method.

What if we are happy with only sorting on one attribute of the Album class? In this case, we do not need to create additional classes implementing IComparer. Instead, we can have our Album class implement IComparable.

Let's assume a new class, “ModernAlbum.” ModernAlbum inherits all its functionality from Album, and it implements the IComparable interface.

class ModernAlbum : Album, System.IComparable
{
    ... more code here ...
    
    // IComparable Members
    public int CompareTo(object obj)
    {
        ModernAlbum modernAlbum = (ModernAlbum)obj;
        return String.Compare(this.Artist, modernAlbum.Artist);
    }
}

Let's assume the following ArrayList of ModernAlbums.

ModernAlbum modernAlbum1 = new ModernAlbum("Counting Crowes", "Modern Rock", "Hard Candy", "2002");
ModernAlbum modernAlbum2 = new ModernAlbum("Whitesnake", "80's Rock", "Greatest Hits", "1985");
ModernAlbum modernAlbum3 = new ModernAlbum("Ben Folds", "Piano Rock", "Army", "1999");
ModernAlbum modernAlbum4 = new ModernAlbum("Phish", "Jam Bands", "Hoist", "1994");
ModernAlbum modernAlbum5 = new ModernAlbum("ACDC", "Hard Rock", "Powerage", "1978");
ModernAlbum modernAlbum6 = new ModernAlbum("Led Zeppelin", "Classic Rock", "Coda", "1982");

ArrayList modernAlbumList = new ArrayList();
modernAlbumList.Add(modernAlbum1);
modernAlbumList.Add(modernAlbum2);
modernAlbumList.Add(modernAlbum3);
modernAlbumList.Add(modernAlbum4);
modernAlbumList.Add(modernAlbum5);
modernAlbumList.Add(modernAlbum6);

Now, in order to sort the ArrayList of ModernAlbum objects, all we need to do is call the ArrayList's Sort() method. This will sort the object in the ArrayList based upon the CompareTo() method defined in the class.

modernAlbumList.Sort();

Now if we display our modernAlbumList objects, they will be sorted.

As ArrayList.Sort() is called, the CompareTo() method of the ModernAlbum object is called and executed. The current instance of the class is represented by "this," and it is compared to each object in the ArrayList, determining if it is less than, equal to, or greater than it.

Using either IComparer or IComparable will acheive the initial objective of sorting on attributes of a class. If we desire the ability to sort on additional attributes of the class, we would create additional classes implementing IComparer and pass those into our ArrayList.Sort() method. Both are simple to use and implement.

Wednesday, October 12, 2005 3:55:50 PM (Mountain Standard Time, UTC-07:00) | Comments [0] | Technology#
MuellerDesigns.net
Search
On This Page
The Split Personality of the Tester/Developer
Cross Site Scripting (XSS)
Creating files with FSUTIL
PowerShell Management Library for Hyper-V
Installing Windows 7
Installing Linux in Hyper-V
Internet Explorer 8 Release Candidate 1
PowerShell Documentation
Automate Daily Tasks with PowerShell
SketchPath XPath Editor
Software Testing - Revisited
Architecting Buildings and Software
NBCOlympics.com with Silverlight
Marker Interfaces and C# Attributes
Most Popular
JavaScript ReplaceAll Functionality
What is polymorphism?
What is composition?
Sorting with IComparable and IComparer
Applying the Observer Pattern in ASP.NET
MVP in ASP.NET
What is abstraction?
What is encapsulation?
What is a class?
What is inheritance?
Authentication in ASP.NET
Calendar Controls
XPathNavigator.CheckValidity new for 2.0
SQL Server 2005 Connection Issues
Auto-attach to process '[####] aspnet_wp.exe' on m...
What is an object?
FreeTextBox
VMWare and VPC
An Example of Reflection using C#
Changing File Ownership In Vista and Longhorn
Archive
Links
Categories
My Local Blog Map
Blogroll
About
Powered by:

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2010
MuellerDesigns.net

Sign In

Help Those In Need
The Hunger Site
Ronald McDonald House Charities (RMHC) of Western Washington & Alaska