Monday, October 20, 2008

IComparable and IComparer

System.Collections.Generic

These two interface were really confusing for me in the begining maybe because of the similarity in the names, but once you understand how it works , they will look simple.

Both of these interfaces provide the same functionality- ability to sort and compare objects.

When you use List<T>.Sort() method , it calls the default comparer
and the overloaded List<T>.Sort(Icomparer) requires you to pass a comparer object.. Let us see more on this...

IComparable<T>

The IComparable interface when implemented provides the means to define a default comparison functionality for a given object. Implement one method - CompareTo() .

public class Customer : IComparable<Customer>{
// The underlying temperature value.
protected m_name = "Sree";

public int CompareTo(Customer other) {
return m_value.CompareTo(other.m_name);
}
}

Because the CompareTo() method is strongly typed , it is not nec to check for the correct data type.

But this Inteface has certain limitations and drawbacks-

This is great if we are happy with only sorting on one attribute (Name) of the Employee class.

if we would like to know how the sort is implemented, we would either have to look at the documentation (if there are, any) or open the Employee class implementation code to understand the sorting logic. This makes IComparable pattern less readable.


IComparer<T>

Enter Icomparer<T> interface , does the same job as Icomparable and defines the sort ranking for any two objects, Except that we dont implement the sorting logic within the same class .

Since you define each comparison logic in seperate classes, you can have multiple ways to sort and compare the objects. And the naming convention of the comparer class (NameComparer, AgeComparer etc ) makes it more readable .

Icomparer<T> exposes the Compare() method.

public class CustomerNameComparer: IComparer<Customer> {
public int Compare(Customer x, Customer y) {
//compare the name fields... }
}

public class CustomerAgeComparer: IComparer<Customer> {
public int Compare(Customer x, Customer y) {
//compare the age fields...
}

//let us use the new object initialier syntax to populate the csuomter list..

List<Customer> customers = new List<Customer>{
new Customer(){ Name="Sree", Age=8 },
new Customer(){ Name="Chris", Age=2},
new Customer() { Name="Helena", Age=14}};

//sort based on name..
customers.Sort( new CustomerNameComparer() );

//and sort based on age...
customers.Sort( new CustomerAgeComparer() );

Final note-
If you dont implement the IComparable interface and CompareTo() method in Customer class and try to call the List<Customer>.Sort() method , you will get an exception.

IEqualityComparer<T> - is a special comparer only used for equality comparison and not sorting and ordering.



-Sree

No comments: