views:

248

answers:

3

The MSDN article here states, that the default implementation of GetHashCode() does not guarantee unique results and should be not used as an identifier. So my question is whether DateTime.Now has its own implementation that would give out unique hashes. Thx for help

A: 

DateTime.Now returns a DateTime value which I am sure has its own implementation of the hash code. Here is the implementation.

public override int GetHashCode()
{
    long internalTicks = this.InternalTicks;
    return (((int) internalTicks) ^ ((int) (internalTicks >> 0x20)));
}
ChaosPandion
A: 

No, it doesn't.

DateTime internally stores its value as a long containing 100-nanosecond untis since 01/01/0001.

Since GetHashCode returns a 32-bit integer, it's impossible for it to be completely unqiue.

Here is DateTime's implementation:

public override int GetHashCode() {
    Int64 ticks = InternalTicks;
    return unchecked((int)ticks) ^ (int)(ticks >> 32); 
}
SLaks
Hmmm, Why is yours different?
ChaosPandion
I got it from the reference source code.
SLaks
I got mine from Reflector.
ChaosPandion
It's the same, the compiler removed the unnecessary unchecked keyword.
Hans Passant
+7  A: 

First, it would be a mistake to rely on the particular implementation of GetHashCode for DateTime. That is something that is hidden from you. Relying on hidden details is a bad code smell; they could change on you at any moment and break your code.

Second, it turns out that DateTime internally stores a 64-bit integer DateTime.Ticks that measures the number of 100-nanosecond units since the epoch (midnight on January 1, 0001). Therefore, DateTime instances require at least 64-bits of information. But hash codes are 32-bit integers and therefore hash codes can not be unique (you can not map 64-bit space to 32-bit space without collisions).

To be explicit, you can see the source code for DateTime.GetHashCode:

public override int GetHashCode() {
    long internalTicks = this.InternalTicks;
    return (((int) internalTicks) ^ ((int) (internalTicks >> 0x20)));
}

As you can see, it does some "folding" to squeeze InternalTicks into a 32-bit integer.

In general, do not rely on hash codes being unique. The input space is generally larger than the space being hashed to (the space of all 32-bit integers).

If you absolutely must have a unique key to represent a DateTime object, use DateTime.ToBinary. This will provide you with a 64-bit integer that is unique and can be used to reconstitute the DateTime (use DateTime.FromBinary).

Jason
thx a lot for explaining
Jaker