Subscribe to Sergio Tapia - Lost in the GC.        RSS Feed
-----

Overriding Equals and GetHashCode for your custom types.

Icon Leave Comment
I decided to finally sit down and work through a couple examples on how to override Equals and GetHashCode for a custom type.

Reasons why you would want to do this:

  • You need to be able to compare between two types easily.
  • You want to be able to use your custom type in a HashTable.


Youíve been there before, you need to verify if a certain item is already in the collection, but you donít quite feel youíve done it in the correct manner. Your inner programmer is itching somewhere and you just know thereís a better way.

Let me show you how with a simple example.

First letís create our custom class, Person.

public class Person
{
    public string IdNumber { get; set; }
    public string Name { get; set; }
}



In order to accomplish our comparing, we're going to make use of the IEquatable interface. In this case IEquatable.

We're going to override the Equals method, the GetHashCode method, and also the == and != operators, to enable us to use those in our code.

public class Person : IEquatable<Person>
{
    public string IdNumber { get; set; }
    public string Name { get; set; }
    public string LastName { get; set; }
    public DateTime DateOfBirth { get; set; }

    public bool Equals(Person otherPerson)
    {
        if (IdNumber == otherPerson.IdNumber)
            return true;
        else
            return false;
    }

    public override bool Equals(object obj)
    {
        if (obj == null)
            return base.Equals(obj);

        if (!(obj is Person))
            return false;
        else
            return Equals(obj as Person);
    }

    public override int GetHashCode()
    {
        return IdNumber.GetHashCode();
    }

    public static bool operator ==(Person person1, Person person2)
    {
        return person1.Equals(person2);
    }

    public static bool operator !=(Person person1, Person person2)
    {
        return (!person1.Equals(person2));
    }
}



Great!

Notice we're depending on the IdNumber for our comparison, and also for our HashCode. That's going to be our 'fingerprint'. :)

Here's an example of how we can now use this in our production code:

class Program
{
    static void Main(string[] args)
    {
        Person sergio = new Person() { IdNumber = "1", Name = "Sergio" };
        Person lucille = new Person() { IdNumber = "2", Name = "Lucille" };

        List<Person> people = new List<Person>(){
            sergio,
            lucille
        };

        Person lucille2 = new Person() { IdNumber = "2", Name = "Lucille" };
        if (people.Contains(lucille2))
        {
            Console.WriteLine("Already exists.");
        }

        Console.ReadKey();
    }
}


If you've made it this far congratulations, you can say you know how to implement a custom comparer. :)

However, here are some things you should be aware of:

  • The integer returned the GetHashCode method should never change. Always make sure you get the hashcode of something immutable.
  • Similarly, the integer of GetHashCode should never change while it's in a structure that depends on it being stable. For example, a Dictionary.


Thanks for reading.

0 Comments On This Entry

 

Trackbacks for this entry [ Trackback URL ]

There are no Trackbacks for this entry

0 user(s) viewing

0 Guests
0 member(s)
0 anonymous member(s)

About Me

Posted Image


Bienvenidos! I'm a USA ex-pat living in Bolivia for the past 10 years. Web development is my forte with a heavy lean for usability and optimization. I'm fluent in both English and Spanish. I guest write for the popular Python website Python Central. Visit my website.

Categories