BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

.NET Framework
.NET 2.0+

Implementing IComparer<T>

The generic IComparer<T> interface was introduced with the .NET framework version 2.0. It is used to compare two values to determine which is the larger. The interface is used in many standard .NET methods, particularly those that sort information.

IComparer<T>

The IComparer<T> interface was added to the .NET framework in version 2.0. Like the IEqualityComparer<T> interface, implementations compare two values. However, rather than returning a Boolean value that specifies whether or not the two values match, IComparer<T> instances are used to determine which of two non-matching values is the larger. This is useful when performing sort operations. Indeed, a number of standard .NET methods, including LINQ's OrderBy standard query operator, include a parameter that accepts a comparer to permit control of the ordering.

You can create your own implementations of IComparer<T> that allow you to sort your own custom types or to modify the ordering of existing classes or structures. This article's sample code includes two such comparers, which sort Customer objects according to the name of the customer or their annual spend.

Implementing the Interface

Before we start to create the two comparers we need a class to compare. We will use a class that represents a customer, with a name held in Forename and Surname properties and an annual spend, to the nearest pound, in the AnnualSpend property.

Create a console application and add the Customer class shown below:

public class Customer
{
    int _annualSpend;
    string _forename;
    string _surname;

    public int AnnualSpend
    {
        get { return _annualSpend; }
        set { _annualSpend= value; }
    }

    public string Forename
    {
        get { return _forename; }
        set { _forename = value; }
    }

    public string Surname
    {
        get { return _surname; }
        set { _surname = value; }
    }
}

Creating the Annual Spend Comparer

With the Customer class defined, we can start to create the first comparer. This will compare the annual spends of two customers and return a value that indicates if the first customer's spend is greater than, less than or equal to that of the second customer. The class will implement IComparer<T> so that it may be used with standard .NET methods. The generic type parameter will be fixed as Customer.

Start by creating a new class named, "AnnualSpendComparer". Make the class public and add the interface to the declaration, as follows:

public class AnnualSpendComparer : IComparer<Customer>
{
}

IComparer<T> Member

The IComparer<T> interface is very simple, defining a single method, Compare. The method returns an integer that describes the ordering of the two items being compared. If both values are equivalent, the method should return zero. If the first argument has a lower value than the second, the result should be any negative integer value. If the second argument is the larger, the result can be any positive integer. Although it may seem strange initially, basing the ordering on the sign of the result, rather than its magnitude, makes some implementations of IComparer<T> very simple indeed.

Implementing Compare

To implement the Compare method for the AnnualSpendComparer, add the code shown below. This method simply subtracts the second argument's spend from that of the first customer. If the second spend is higher the method returns the difference as a negative amount. If the second customer has a lower spend the result will be positive. Finally, if both spends are the same, the result will be zero. This means that simple subtraction fulfils all requirements of the interface.

public int Compare(Customer customer1, Customer customer2)
{
    return customer1.AnnualSpend - customer2.AnnualSpend;
}

Creating the Customer Name Comparer

The second comparer will compare two customers based upon their surname and forename. Where the surnames of the customers match, they will be sorted according to the forename. In this case we cannot obtain a result by simple subtraction. We start by using the String class' static Compare method to compare the surnames. String.Compare uses the same principles as the method in the IComparer<T> interface. If the result of the comparison it not zero, we can just return it.

If the comparison of surnames yields a zero result, the surnames match. In this case we must compare the forenames. Again we use String.Compare and simply return the result. The full implementation is shown below.

public class NameComparer : IComparer<Customer>
{
    public int Compare(Customer customer1, Customer customer2)
    {
        int surnameComparison = string.Compare(customer1.Surname, customer2.Surname);
        if (surnameComparison == 0)
            return string.Compare(customer1.Forename, customer2.Forename);
        else
            return surnameComparison;
    }
}
19 January 2012