GetHashCode and .NET Classes

I made a coding mistake the other day that caused me a lot of grief. I had forgotten that if you define a .NET class and you are going to use a Hashtable to keep track of the objects (typically to prevent duplicate objects) you should override the built in GetHashCode() method and write a custom method. For example, suppose you have a class Employee:

class Employee
  public long empID;
  public string lastName;
  public int yearsExp;

  public Employee(long empID, string lastName, int yearsExp)
    this.empID = empID; this.lastName = lastName; this.yearsExp = yearsExp;
  public override string ToString()
    return this.empID + ":" + this.lastName + ":" + this.yearsExp;

Now suppose you want to add employee objects to a List or an ArrayList or some other collection but you want to prevent duplicates. You could try:

List<Employee> myList = new List<Employee>();
Hashtable ht = new Hashtable();

. . .
Employee e = new Employee(123456789, "Adams", 1);
if (ht.Contains(e.GetHashCode() == false)
  ht.Add(e.GetHashCode(), e);

But this won’t work because two Employee objects which have the same values will (usually) have different GetHashCode() values which means objects with duplicate values would not be caught. For example the code:

Employee e1 = new Employee(123456789, "Adams", 1);
Employee e2 = new Employee(123456789, "Adams", 1);
Console.WriteLine("Employee e1 = " + e1 + " GetHashCode e1 = " + e1.GetHashCode());
Console.WriteLine("Employee e2 = " + e2 + " GetHashCode e2 = " + e2.GetHashCode());

produces as output:

Employee e1 = 123456789:Adams:1 GetHashCode e1 = 37121646
Employee e2 = 123456789:Adams:1 GetHashCode e2 = 57352375

The solution is to override GetHashCode() like so:

public override int GetHashCode()
  return this.empID.GetHashCode() ^
    this.lastName.GetHashCode() ^

Here I use the simple XOR ^ operator to combine the return values from the built-in GetHashCode(). With the overridden GetHashCode() method definews in the Employee class, the same code as above now produces:

Employee e1 = 123456789:Adams:1 GetHashCode e1 = 1177625094
Employee e2 = 123456789:Adams:1 GetHashCode e2 = 1177625094

In other words, objects with the same values now have the same GetHashCode() value.

This entry was posted in Software Test Automation. Bookmark the permalink.