Click here to Skip to main content
15,886,075 members
Articles / Programming Languages / C#
Tip/Trick

Talk about System.Object Equals and GetHashcode

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
14 Mar 2013CPOL1 min read 116.2K   10   2
If two objects are equal, they would better have the same HashCode.

Introduction

Just a simple example to show why we need to override GetHashCode if we override Equals, just understanding why "if two objects are equal, they would better have the same HashCode".

Background

In C#, when we create a class, it is automatically inherited from System.Object, and we inherit the Equals and GetHashCode methods.  We can override them, but if we override Equals without overriding GetHashCode, we will get a warning message: "overrides Object.Equals(object o) but does not override Object.GetHashCode()".

Why is Microsoft warning you this? If you don't plan to use your object as a key for hash collections (like Hashtable, Dictionary, etc.), it is OK. Otherwise you will face a problem.

Using the Code

I define a class and override the Equals method. If the Ids are the same, the two objects are equal. In the RunOverEqualsWithoutHashCode method, I create a Hashtable using HashCodeWalkthrough as key and store 100 items, then I tried to find the A50, but got nothing.

Then if I override the GetHashCode method, I can find the items in the Hashtable.

C#
class HashCodeWalkthrough
{
    //public override int GetHashCode()
    //{
    //    return Convert.ToInt32(id.Substring(1));
    //}

    /// <summary>
    /// If Id is the same,then Equals
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public override bool Equals(object obj)
    {
        if (null == obj) return false;
        HashCodeWalkthrough obj2 = obj as HashCodeWalkthrough;
        if (obj2 == null) return false;
        return this.id.Equals(obj2.Id);
    }

    #region Properties
    string name = string.Empty;

    public string Name
    {
        get { return name; }
        set { name = value; }
    }
    string id = string.Empty;

    public string Id
    {
        get { return id; }
        set { id = value; }
    }
    #endregion
}

private static void RunOverEqualsWithoutHashCode()
{
    //create a 100 items hashtable with HashCodeWalkthrough obj as the key
    Hashtable hash = new Hashtable();
    for (int i = 0; i < 99; i++)
    {
        hash.Add(new HashCodeWalkthrough() { Id = "A" + i, Name = "Name" + i },
            "Value" + i);
    }

    HashCodeWalkthrough search50 = new HashCodeWalkthrough() { Id = "A50", Name = "Name50" };
    Console.WriteLine(hash.ContainsKey(search50));
    Console.WriteLine("Find the 50th in Hashtable");
    string value = hash[search50] as string;
    Console.WriteLine(value);
    
}

public override int GetHashCode()
{
    return Convert.ToInt32(id.Substring(1));
}

Points of Interest

The trick is that when storing data in a hash collection, it uses the object's Hashcode to find a bucket. When getting items, it also uses the key object's Hashcode to search the bucket. Although the two key objects Equals (because we override), they have different Hashcodes (by default System.Object returns a unique ID in the AppDomain for any new object), so when getting, it will find no bucket, so that item will actually be missing.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
China China
Right now I am a college student.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Karsten Gutjahr19-Mar-13 1:55
Karsten Gutjahr19-Mar-13 1:55 
SuggestionGood hints Pin
bensonxiong18-Mar-13 16:48
bensonxiong18-Mar-13 16:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.