Friday, November 20, 2009

Sorting List of Custom Objects

“System.Collections” and “System.Collections.Generic “ namespaces have classes for collections. Collection objects are the specialized objects which can hold multiple objects of other classes. Other classes also refer to collection classes along with non-collection classes. The two different namespaces have non-generic and generic versions of collection classes.
My discussion is focusing on the ArrayList collection class. This discussion also covers the generic version “List<T>"class.

What is ArrayList?
ArrayList is a non-generic collection class. Object of this class can hold list of homogeneous objects. Homogeneous objects means objects of any class (data type). This collection may not have necessarily objects of same type.

ArrayList grows dynamically with addition of new objects. It does not have any fixed length. Initially, empty ArrayList object has capacity of 0 objects. As we add first object, the capacity grows to hold 4 objects. When we add the fifth object, it grows by double to hold 8 objects in it. ArrayList capacity doubles when its capacity is crossed.

List<T> is just the generic version of ArrayList. Generic collection object can have objects of same type only.

Sorting:

ArrayList and List have the sort method already implemented. This sort method works very well for primitive system data types (e.g. int, long etc.). But what about the user-defined types (viz. Class, Struct,Enum)? To order the objects you should know how to compare them. How to acquaint .NET Framework about comparing user-defined data types?

public class Person
{
public string Name;
public int Age;
}
List<person> plist=new <Person>();
… //Add few person objects.
plist.Sort();

Consider we’ve the list of person objects. How sorting will happen, based on Name or Age? What it’ll compare (name or age of persons)? Try it.


Comparison of Person object is possible only if we implement IComparable or IComparer interface. The IComparable interface has single method, CompareTo. See the code below with IComparable interface implementation.


public class Person : IComparable //Change it to IComparable<Person>
{
public string Name;
public int Age;

#region IComparable Members
//Argument will be of Person type if IComparable<Person> is //implemented.
public int CompareTo(Object obj)
{
Person p=obj as Person //Not required if generic IComparable implemented.
return this.Name.CompareTo(p.Name);
}
#endregion
}

IComparable interface has generic variant, IComparable<T> interface. The CompareTo method of IComparable<T> takes object of T as argument. So type-casting of argument is avoided.


Now it’ll sort the Person list with respect to their names. What if we’d like to have the sorting by Age? Change the code.


What if we’d like to have sorting by Age as well as by Name? Then IComparable interface implementation is not sufficed. We’ve to create two implementations (classes) of IComparer interface : NameComparer and AgeComparer. IComparer interface has Compare method accepting two objects. Cast the objects to appropriate type & then compare. Generic version of IComparer is IComparer<T> can be implemented in similar way. It avoids need of type-casting.


NameComparer will have implementation of Compare method based on Name whereas AgeComparer will have implementation based on Age. These classes will not have any other code.


Sort method overload accepts object of IComparer implementation (class) as argument. If our requirement is to compare by Age use object of AgeComparer, or else NameComparer for alphabetical sorting.


public class NameComparer : IComparer
{
#region IComparer Members

public int Compare(object x, object y)
{
Person p = x as Person;
Person q = y as Person;
return p.Name.CompareTo(q.Name);
}

#endregion
}
public class AgeComparer : IComparer
{
#region IComparer Members

public int Compare(object x, object y)
{
Person p = x as Person;
Person q = y as Person;
return p.Age.CompareTo(q.Age);
}

#endregion
}

plist.Sort(new AgeComparer());

That’s all folks!!! Reuse the .NET functionality.
Post a Comment