I have a few applications where I need to create some unique IDs that can't be GUIDs. GUIDs are great if you truly need a globally unique identifier, but they are a bit of overkill when it comes to application that locally unique ids. GUIDS are nice but they are big. If you need to represent them as strings the 38 characters it uses with punctuation is a bit excessive. There's nothing that I hate more than browser querystrings that have 3 GUID IDs embedded in them <g>…

 

The most common places I need these simple ids are for temporary identifiers. For example when I send a request to my Credit Card Processor there's an ID that correlates my invoice with the transaction at the provider. The providers has some odd rules about the invoice numbers so if somebody needs to resubmit the order it won't go through – hence I need to create a new ID. Anyway, a GUID isn't what I'd want here.

 

Invoices too. I tend to give invoices an ID that is not just a number but yet reasonably easy for a user to work with. Handing a 34 digit numeric string isn't going to fly with customers.

 

So… in light of this, what's a good way to create an ID in .NET? In Fox I used to use SYS(2015) for this, which works pretty reliably except in very volume multi-threaded environments. Unfortunately I'm not sure what it uses to generate this id.

 

Invoice.Invno = DateTime.Now.ToString().GetHashCode().ToString("x");

 

which produces something like this:

 

369bf2e0

 

Now, I've never had a problem with this but reading over the documentation of GetHashCode() it indicates that GetHashCode() doesn't generate unique hashcodes. If the value isn't guaranteed to be unique how can it be used as a hash of a value? That's a bit confusing…

 

In regards to strings then it seems to contradict the above:

 

For example, the implementation of GetHashCode provided by the String class returns unique hash codes for unique string values.

 

So, does that mean that any one string representation can be expressed only by a unique hash? I can't imagine this being true.

 

So if I do:

 

Guid.NewGuid().ToString().GetHashCode().ToString("x");

 

469cf3e1

 

Somehow I don't think that this string representation at least is unique… 38 characters represented as 8? Ok 32 bits, but still it's 8 digits and characters limited to hex values.

 

Here's an interesting link that talks about some of the GetHashCode inconsistencies with the documentation:

 

http://www.interact-sw.co.uk/iangblog/2004/06/21/gethashcode

 

Even with that in mind it's not really clear to me if generating a string with the values above would be safe or not.

 

So what other options are there to generate a reasonably unique ID?  Maybe a better way is:

 

DateTime.Now.Ticks.ToString("x")

 

which generates:

 

8c8113da982d75a

 

and which is getting a bit long at 15 characters. Ticks is a 64 bit so it makes sense that the string is a bit longer.

 

Hmm... for the invoice example I mentioned earlier I suppose using a hex representation of the PK would work. Or even a hashcode of the PK. Nope - Integer values persisted aren't properly random (10 turns into a and GetHashCode() for integers just returns the value).

 

What else? How about using part of a GUID string? Is there any part of a GUID that can be dissected and be acceptable as a non-network safe ID?  Doesn't look like it – if you generate new GUIDs every single character changes in the string representation.