Overriding GetHashCode [duplicate]
Asked Answered
H

6

36

As you know, GetHashCode returns a semi-unique value that can be used to identify an object instance in a collection. As a good practice, it is recommended to override this method and implement your own.

My question is - do you override this method when working on custom objects? If so, what algorithm do you use to generate the unique ID?

I was thinking about generating a GUID and then getting integer data from that identificator.

Hardware answered 21/11, 2010 at 21:27 Comment(4)
Have a read of this question and its answers. It outlines a good hash code implementation. There is also a good discussion on overiding GetHashCode for mutable objects here.Coachandfour
I don't know what "semi-unique" means... a value is either unique or it's not, and a hashcode is not unique. Therefore it doesn't allow you to identify an object in a list. And it's not "a good practice" to override GetHashCode, that's something you do when you need to (e.g. to use the object as a key in a dictionary), not because you think it's a good practice.Shorttempered
Using the object as a key can be considered as identifying the object in a collection - that's exactly why I'm looking for input on what is the best algorithm to build the identifier. As of semi-unique IDs: west-wind.com/Weblog/posts/4741.aspxHardware
Dennis, you first need to think what equality behaviour you want. For the default reference-equality (for mutable objects with identity) you have to do exactly nothing.Bio
B
28

When you override GetHashCode() you also need to override Equals(), operator== and operator!= . And be very careful to meet all the requirements for those methods.

The guidelines are here on MSDN. Most important quote:

It is not a good idea to override operator == in mutable types.

Bio answered 21/11, 2010 at 22:7 Comment(10)
From what I understand, that will make no sense because, well, the object won't change it's state.Hardware
What will make no sense?Bio
strings are immutable, have you never used name == "x" ?Bio
Yes, but when you modify a string, you create a new object (e.g. when you use Replace).Hardware
Still, string overrides Equals and all the rest. I'm not getting your point here.Bio
@Dennis: You cannot modify a string, it is immutable. That is not a semantic statement. Calling methods like Replace which return a new string does not modify a string, not literally, and not figuratively. You have to change your mentality here.Coupe
Oh no, I am not saying that string is mutable. I was saying exactly what you just stated - when I call Replace, the string is not modified - a new object is created instead.Hardware
The point is that it's natural to rely on == staying true until you reassign the variable; it is not intuitive to have mutation side effects change the past meaning of == as anything that supports comparison operators by default are value types or immutable. These only change value when you say var = "new value" which explicitly implies a previous == may not be true anymore. References types can change state from other code and methods mutate the object elsewhere could change the equality. Equals does not provide the same expectation because it is a method definition, not syntax.Doykos
Just to clarify: Non-immutable is the same thing as mutable?Chrismatory
@Chrismatory - yes, but mutable is kind of the norm in imperative languages like C#.Bio
P
31

If you use resharper it can generate the GetHashCode(), Equals and operator method bodies for you.

Access this menu by pressing Alt+Insert.

http://www.jetbrains.com/resharper/webhelp/Code_Generation__Equality_Members.html

Principe answered 2/12, 2010 at 16:52 Comment(0)
B
28

When you override GetHashCode() you also need to override Equals(), operator== and operator!= . And be very careful to meet all the requirements for those methods.

The guidelines are here on MSDN. Most important quote:

It is not a good idea to override operator == in mutable types.

Bio answered 21/11, 2010 at 22:7 Comment(10)
From what I understand, that will make no sense because, well, the object won't change it's state.Hardware
What will make no sense?Bio
strings are immutable, have you never used name == "x" ?Bio
Yes, but when you modify a string, you create a new object (e.g. when you use Replace).Hardware
Still, string overrides Equals and all the rest. I'm not getting your point here.Bio
@Dennis: You cannot modify a string, it is immutable. That is not a semantic statement. Calling methods like Replace which return a new string does not modify a string, not literally, and not figuratively. You have to change your mentality here.Coupe
Oh no, I am not saying that string is mutable. I was saying exactly what you just stated - when I call Replace, the string is not modified - a new object is created instead.Hardware
The point is that it's natural to rely on == staying true until you reassign the variable; it is not intuitive to have mutation side effects change the past meaning of == as anything that supports comparison operators by default are value types or immutable. These only change value when you say var = "new value" which explicitly implies a previous == may not be true anymore. References types can change state from other code and methods mutate the object elsewhere could change the equality. Equals does not provide the same expectation because it is a method definition, not syntax.Doykos
Just to clarify: Non-immutable is the same thing as mutable?Chrismatory
@Chrismatory - yes, but mutable is kind of the norm in imperative languages like C#.Bio
S
1

In my personal usage, I only override when overriding equals method too. Generally, I do this for objects I know that I might run a LINQ to Objects query on, or some other comparison operation.

I usually return, if say a LINQ to SQL entity or DTO object, the primary key value. Whatever you return, if you don't store the value locally, it may produce an unexpected result.

HTH.

Selfimportant answered 21/11, 2010 at 21:33 Comment(0)
L
1

I would normally override hashcode and equality checking methods for data classes (i.e. classes where the value semantics makes sense). Have a look at this question for a common implementation. If you do override hashcode override equals. Using a GUID is a pretty terrible idea because you want two objects which are different instances but have the same value to have the same hashcode and for equals to return true.

Lydon answered 21/11, 2010 at 21:43 Comment(0)
E
0

you only need to override GetHashCode if you are overriding Equals. The default GetHashCode is implemented by the runtime in a similar way you wanted to do it - every object has a hidden field assigned by the runtime.

How to override GetHashCode

Actually your IDE should do this for you - when you type "override GetHashCode" the IDE should generate this boilerplate code. Visual Studio does not do it but SharpDevelop does.

Equip answered 21/11, 2010 at 21:41 Comment(3)
The default implementation of the GetHashCode method does not guarantee unique return values for different objects. Consequently, the default implementation of this method must not be used as a unique object identifier for hashing purposes. From: msdn.microsoft.com/en-us/library/system.object.gethashcode.aspxLydon
in VS one has to use the equals snippet insteadOotid
@Lydon - I read this. Does it mean that you should always override GetHashCode when you want to store your objects in a Dictionary? I don't think so - almost noone does this. The default implementation works fine for purposes of Dictionary. It is not perfect, but fine: https://mcmap.net/q/146319/-net-unique-object-identifierEquip
B
-2

Generally I use the aggregated GetHashCode from the component properties of the class. E.g.

public class Test
{
  public string Text { get; set; }
  public int Age { get; set; }

  public override GetHashCode()
  {
    int result = 
      string.IsNullOrEmpty(Text) ? 0 : Text.GetHashCode()
      + Age.GetHashCode();

    return result;
  }
}
Balas answered 21/11, 2010 at 21:30 Comment(3)
This is not a very goo way to do it, see #263900Equip
In general adding isn't good for creating a compound hashcode. But in this specific example I see no problem with it. But of course the overriding GetHashCode without overriding Equals doesn't make much sense.Ootid
Well, you learn something every day!Balas

© 2022 - 2024 — McMap. All rights reserved.