Click here to Skip to main content
15,850,606 members
Articles / Programming Languages / C#

Using GetHashCode correctly

Rate me:
Please Sign up or sign in to vote.
3.92/5 (5 votes)
3 Oct 2011CPOL2 min read 31.5K   2   3
It may not always be obvious what makes a good source for a HashCode.
This one has caught me out badly and I have posted to a number of forums over the years trying to solve it, but I have finally found the answer.

I used to think that overriding GetHashCode was only required to provide a unique identifying key for each instance in a custom collection, and that selecting a subset of the properties (such as would be used for a primary key) would be sufficient. And mostly it is. Where I came unstuck was not realizing that should the user change any of the values making up this "primary key", which typically happens when a user edits the properties of a new instance, the HashCode would also alter for that instance, and that any controls bound to the collection containing that instance would no longer be able to locate it.

For me, this was evidenced in the selected items collection of a ListView or ListBox control losing track of the instance that was altered, and not being able to remove it from that collection resulting in more than one row being visibly selected when the user clicked on any other row.

To put this into perspective, I often create WPF forms that contain a ListView over a particular collection, and a set of controls where the user can manipulate the properties of the selected instance in the collection. Added to this a button to allow creating a new instance, and one for deleting an existing instance, and you have a very powerful yet simple way of managing data manipulation on one form, without all the hassles of DataGrids or having to resort to sub forms.

For adding a new item, the user clicks the New button and the code behind goes about creating the new instance adding it to the collection, and selecting it. If the collection is Observable, and is bound to the ListView, all the other data entry controls only need to bind to the object properties, and then you group them with a DataContext and bind that to the current row in the ListView, and you have your data entry form.

But, once the user starts entering data, should they modify any property taking part in identifying the new instance to the ListView, things start going pear shaped. The difficulty I have had in identifying exactly what was going on has been that nowhere have I seen it referenced that UI controls, like ListView, depended on the GetHashCode method of the collections type, and there is no way to debug this problem.

What I do now, to get around this specific problem, is to always use a Random number for my HashCode source. You don't have to persist the number, but you do have to make sure the number is generated by the ctor, and that it is only used by the GetHashCode method.

I hope this post helps others out there who might be experiencing similar problems.


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

Written By
Web Developer
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

GeneralReason for my vote of 2 you say "correctly" means make a ra... Pin
johannesnestler14-Oct-11 2:39
johannesnestler14-Oct-11 2:39 
GeneralFor reference types, you can get the same behaviour by not o... Pin
Richard Deeming15-Sep-11 9:52
mveRichard Deeming15-Sep-11 9:52 
QuestionUse Interlocked.Increment Pin
Paulo Zemek5-Sep-11 13:45
mvaPaulo Zemek5-Sep-11 13:45 
Creating a static int as the hashcode generator and, during the construction calling hahscode = Interlocked.Increment(ref _hashCodeGenerator) will solve the problem, will be thread safe and, at least during the execution time, will completely avoid duplicate values.

But, to be honest, I think the real source of the problem is the way you are working with your classes.
If the data is required for the database, then you should determine its (unchangeable) primary key before putting the object into a list. Note that it is usual to put some changeable properties as the primary key when they are small (like state names) but even rare, such things can change, so it is always better to have another unchangeable value.

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.