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 IEqualityComparer<T>

IEqualityComparer<T> is a generic interface defined in the .NET framework version 2.0 and used in many standard classes, including several LINQ operators. The interface can be implemented to allow customised comparison of values and objects.

IEqualityComparer<T>

The IEqualityComparer<T> interface was introduced into the .NET framework with version 2.0. It is used by many standard methods that carry out value comparisons. It allows you to define exactly how those comparisons should be made. For example, the static OrdinalIgnoreCase property of the StringComparer class returns a case-insensitive comparer for strings. If you were to compare strings that differed only in capitalisation using another comparer or the equality operator you may see different results.

You can create your own implementations of IEqualityComparer<T> that work with your own classes and structures. These can then be used with comparison methods, including LINQ standard query operators, to allow greater control of the results. In this article we will create such a class that compares customer objects. Rather than checking that the references for two Customer instances match, we will compare a unique ID property. If the IDs match we will deem the two Customers to be equal, even if the other properties differ.

Implementing the Interface

To begin, create a new console application and add the following Customer class. This is a very simple type containing three properties and no business logic. The properties define a unique identifier, a forename and a surname for each customer.

public class Customer
{
    Guid _id;
    string _forename;
    string _surname;

    public Guid Id
    {
        get { return _id; }
        set { _id = value; }
    }

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

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

Creating the Comparer

Next we can declare the comparer class. We'll name it, "CustomerComparer". The class must implement the IEqualityComparer<T> interface to allow it to be used with .NET classes that perform comparisons. In this case we'll fix the type parameter as Customer, as we won't need it to compare any other type.

public class CustomerComparer : IEqualityComparer<Customer>
{
}

IEqualityComparer<T> Members

The IEqualityComparer<T> interface defines two members, both of which are methods. These are:

  • Equals. This method accepts two values or objects to be compared. If they are deemed to match, the method returns true. If not, it returns false. It is important that the order in which the objects are supplied does not affect the result and that if the same object is provided to both parameters the method returns true.
  • GetHashCode. This method is used to generate an integer hash code for the single provided value or object. It is essential that the hash codes for two values that are deemed equal by the Equals method are the same. In some cases the method can return the hash code generated by the GetHashCode method of the argument. However, if two objects that are deemed equal generate different hash codes you must create the value in another manner. This is the case with the standard case-insensitive string comparers.

Implementing Equals

Let's continue implementing the interface for our CustomerComparer class. We'll add the Equals method next. As we only care about the two ID values being the same, the method can return the result of a comparison of the two globally unique identifiers (GUIDs). Add the code shown below to the class:

public bool Equals(Customer customer1, Customer customer2)
{
    return customer1.Id == customer2.Id;
}

Implementing GetHashCode

We now need to implement the GetHashCode method. We can't return the hash code of the Customer object as this will vary for Customers that we want to be equal. However, as we are only comparing the IDs, we can return the hash code of the customer's ID property.

public int GetHashCode(Customer customer)
{
    return customer.Id.GetHashCode();
}

Testing the Comparer

We can test the CustomerComparer class by creating several Customers and comparing them. The code below instantiates three customers. The first two have matching IDs so comparing them generates a true result and both have the same hash code when obtained via the comparer. The third customer has the same name as the first but a different ID. This means that the comparison of the first and third customers returns false and the two objects' hash codes differ.

Customer customer1 = new Customer();
customer1.Id = new Guid("12345678901234567890123456789012");
customer1.Forename = "Bob";

Customer customer2 = new Customer();
customer2.Id = new Guid("12345678901234567890123456789012");
customer2.Surname = "Smith";

Customer customer3 = new Customer();
customer3.Id = new Guid("11111111111111111111111111111111");
customer3.Forename = "Bob";

CustomerComparer comparer = new CustomerComparer();

bool same1and2 = comparer.Equals(customer1, customer2);  // true
bool same1and3 = comparer.Equals(customer1, customer3);  // false

int hash1 = comparer.GetHashCode(customer1);             // -1876532676
int hash2 = comparer.GetHashCode(customer2);             // -1876532676
int hash3 = comparer.GetHashCode(customer3);             // 285212689
14 January 2012