Given the following key:
int key = Guid.NewGuid().GetHashCode();
Is this key unique as the uniqueness of Guid?
Given the following key:
int key = Guid.NewGuid().GetHashCode();
Is this key unique as the uniqueness of Guid?
The pigeonhole principle says no. A GUID has 16 bytes of information* - 128 bits. An int
has only 32 bits of information.
There are 2128 possible GUIDs, and 232 possible hash codes - so you can't possibly have a different hash code for each GUID.
There's more than that though - GetHashCode()
is never meant to represent uniqueness. If it can, then that's great - but it doesn't have to, even when there are enough int
values available to do so.
It would be entirely valid for int.GetHashCode()
to return (say) the value divided by two... so -1, 0 and 1 would all get a hash code of 0; 3 and 4 would get a hash code of 2 etc. It wouldn't be good (and it would be slower than just returning the value) - but it would be a valid implementation. It would satisfy all the constraints of GetHashCode
- namely that if you call it on two equal values, it will return the same hash code.
In fact, returning a constant for all values is a valid implementation - although a pretty useless one, in that it renders the normally-fast lookup of a hash table into an O(N) operation.
* - To clarify due to comments, the .NET GUID will allow these 128 bits to be set arbitrarily as far as I'm aware; randomly generated GUIDs follow a stricter pattern so there aren't 2128 different values which would be randomly generated. Still more than 232 though.
Guid
type, and I still maintain that there are 2^128 possible values for that type. –
Venery GetHashCode
if two different instances can have the same value? It can't be used reliably either to confirm that 2 things are the same, or that 2 things are different! –
Pinebrook Just today I've noticed another problem of the Guid.GetHashCode()
: in Microsoft .NET implementation, not every "byte" of the Guid
is hashed: there are 6 bytes of the Guid
that aren't hashed, so any change to one of them won't ever change the hash code.
We can see it in the reference source:
return _a ^ (((int)_b << 16) | (int)(ushort)_c) ^ (((int)_f << 24) | _k);
so the _d
, _e
, _g
, _h
, _i
, _j
bytes aren't hashed. This has an important impact with "sequential" Guid
s, like:
c482fbe1-9f16-4ae9-a05c-383478ec9d13
c482fbe1-9f16-4ae9-a05c-383478ec9d14
c482fbe1-9f16-4ae9-a05c-383478ec9d15
...
c482fbe1-9f16-4ae9-a05c-383478ec9dff
c482fbe1-9f16-4ae9-a05c-383478ec9e00
c482fbe1-9f16-4ae9-a05c-383478ec9e01
with Guid
like these, the number of different hashes generated is very small (256 different values), because the 3478ec9d
/3478ec9e
won't be hashed.
GetHashCode()
are the 60 bit timestamp and parts of the MAC address. For version 4 UUID's (which you get from Guid.NewGuid()
) almost all bytes of the GUID are random. So in these cases the algorithm seems OK. –
Stockdale GetHashCode()
returns an integer - it cannot be as unique as a Guid
, so no - there might be collisions and uniqueness is not guaranteed.
The point of a hash code is that it should distribute evenly across the hash range so that collisions should be generally rare, you always have a chance of collision though and have to accommodate for that.
I was having exactly the problem xanatos describes in another answer. I have a class where two Guid
values are used to distinguish different objects, and I found I was getting a horrible number of collisions (my Guids are not randomly generated). Here is the code I used to solve the problem. Guid1
and Guid2
are the properties of type Guid
that distinguish the objects. The code follows the approach described by Jon Skeet here.
public override int GetHashCode()
{
int hash = 173;
foreach (Byte b in Guid1.ToByteArray().Concat(Guid2.ToByteArray()))
{
hash = hash * 983 + b;
}
return hash;
}
A Guid is a 128-bit number. An int is a 32-bit number, so it can't be "as unique" as the Guid.
Besides, GetHashCode returns ... a hash code, it's not meant to be unique in any way. See other discussions here on SO about why GetHashCode() exists.
© 2022 - 2024 — McMap. All rights reserved.
Guid
constructor with any values you want. Do you have any evidence to the contrary? – Venery