I try to use long as unique id within our C# application (not global, and only for one session) for our events. Do you know if the following will generate an unique long id?
public long GenerateId()
{
byte[] buffer = Guid.NewGuid().ToByteArray();
return BitConverter.ToInt64(buffer, 0);
}
Why we not use GUID directly? We think 8 bytes long is good enough.
You cannot distill a 16-bit value down to an 8-bit value while still retaining the same degree of uniqueness. If uniqueness is critical, don't "roll your own" anything. Stick with GUIDs unless you really know what you're doing.
If a relatively naive implementation of uniqueness is sufficient then it's still better to generate your own IDs rather than derive them from GUIDs. The following code snippet is extracted from a "Locally Unique Identifier" class I find myself using fairly often. It makes it easy to define both the length and the range of characters output.
using System.Security.Cryptography;
using System.Text;
public class LUID
{
private static readonly RNGCryptoServiceProvider RandomGenerator = new RNGCryptoServiceProvider();
private static readonly char[] ValidCharacters = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789".ToCharArray();
public const int DefaultLength = 6;
private static int counter = 0;
public static string Generate(int length = DefaultLength)
{
var randomData = new byte[length];
RandomGenerator.GetNonZeroBytes(randomData);
var result = new StringBuilder(DefaultLength);
foreach (var value in randomData)
{
counter = (counter + value) % (ValidCharacters.Length - 1);
result.Append(ValidCharacters[counter]);
}
return result.ToString();
}
}
In this instance it excludes 1 (one), I (i), 0 (zero) and O (o) for the sake of unambiguous human-readable output.
To determine just how effectively 'unique' your particular combination of valid characters and ID length are, the math is simple enough but it's still nice to have a 'code proof' of sorts (Xunit):
[Fact]
public void Does_not_generate_collisions_within_reasonable_number_of_iterations()
{
var ids = new HashSet<string>();
var minimumAcceptibleIterations = 10000;
for (int i = 0; i < minimumAcceptibleIterations; i++)
{
var result = LUID.Generate();
Assert.True(!ids.Contains(result), $"Collision on run {i} with ID '{result}'");
ids.Add(result);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With