I'm trying to override GetHashCode
to ensure uniqueness, since i use the instances as keys in a dictionary:
IDictionary<Base, int> _counts = new Dictionary<Base,int>();
The two classes I have an issue with are:
class sealed First : Base
{
public MyEnum1 value;
public ExtrasEnum extras;
public override int GetHashCode()
{
unchecked
{
return ((int)value* 397) ^ (int)extras;
}
}
//Other stuff
}
class sealed Second : Base
{
public MyEnum2 value;
public ExtrasEnum extras;
public override int GetHashCode()
{
unchecked
{
return ((int)value* 397) ^ (int)extras;
}
}
//Other stuff
}
However. The issue is that when the value
and extras
int values become the same, then the hash codes will be equal.
The calculation was the recommended one by Resharper.
How do i ensure that the hashcodes for theese classes does not be come the same?
Just mix it up a little with another prime number, or?
EDIT:
Just to explain. I need that if to instances of First
has the same value
and extras
values, then these two instances must be considered the same, but if an instance of First
, and a instance of Second
have the same int values of value
and extras
, then these must not be considered the same.
I'm not looking into performance, but just to ensure that same class instances are equal, and different class instances are different.
It isn't very difficult to generate a perfect hash from enum members. With the assumption that they won't have more than 256 members, you can write a fast one with:
public override int GetHashCode() {
return ((int)value << 8) ^ (int)extras;
}
And not generate any collisions at all by writing Second.GetHashCode() as:
public override int GetHashCode() {
return ((int)value << 16) ^ (int)extras;
}
Very simple and perfect, but doesn't scale of course when you add more derived classes. It really doesn't need to, you are micro-optimizing without having any insight in how this really speeds up your code. Do keep in mind that a perfect hash does not avoid bucket collisions in the dictionary, the bucket index is calculated by taking the modulo of the hash code with a prime. The larger the number of items in the dictionary, the larger the prime.
Just don't do this at all. And always use a profiler if you want to know if you need to anyway.