I think that the documentation regarding GetHashcode is a bit confusing.
On one hand, MSDN states that the hashcode of an object should never change , and be constant
On the other hand, MSDN also states that the return value of GetHashcode should be equal for 2 objects, if those 2 objects are considered to be equal.
MSDN:
A hash function must have the following properties:
- If two objects compare as equal, the GetHashCode method for each object
must return the same value. However,
if two objects do not compare as
equal, the GetHashCode methods for the
two object do not have to return
different values.
- The GetHashCode method for an object must consistently return the
same hash code as long as there is no
modification to the object state that
determines the return value of the
object's Equals method. Note that this
is true only for the current execution
of an application, and that a
different hash code can be returned if
the application is run again.
- For the best performance, a hash function must generate a random
distribution for all input.
Then, this means that all your objects should be immutable, or the GetHashcode method should be based on properties of your object that are immutable.
Suppose for instance that you have this class (naive implementation):
public class SomeThing
{
public string Name {get; set;}
public override GetHashCode()
{
return Name.GetHashcode();
}
public override Equals(object other)
{
SomeThing = other as Something;
if( other == null ) return false;
return this.Name == other.Name;
}
}
This implementation already violates the rules that can be found in MSDN.
Suppose you have 2 instances of this class; the Name property of instance1 is set to 'Pol', and the Name property of instance2 is set to 'Piet'.
Both instances return a different hashcode, and they're also not equal.
Now, suppose that I change the Name of instance2 to 'Pol', then, according to my Equals method, both instances should be equal, and according to one of the rules of MSDN, they should return the same hashcode.
However, this cannot be done, since the hashcode of instance2 will change, and MSDN states that this is not allowed.
Then, if you have an entity, you could maybe implement the hashcode so that it uses the 'primary identifier' of that entity, which is maybe ideally a surrogate key, or an immutable property.
If you have a value object, you can implement the Hashcode so that it uses the 'properties' of that value object. Those properties make up the 'definition' of the value object. This is of course the nature of a value object; you're not interested in it's identity, but rather in it's value.
And, therefore, value objects should be immutable. (Just like they are in the .NET framework, string, Date, etc... are all immutable objects).
Another thing that comes in mind:
During which 'session' (I don't know really how I should call this) should 'GetHashCode' return a constant value.
Suppose you open up your application, load an instance of an object out of the DB (an entity), and get its hashcode. It will return a certain number.
Close the application, and load the same entity. Is it required that the hashcode this time has the same value as when you loaded the entity the first time ?
IMHO, not.