Search code examples
c#guiduniqueidentifieruid

How do I create a unique identifier that does not contain numbers?


I'm looking to use some sort of unique identifier within a .resx file but it does not allow the key to begin with a number. Rather than cycling through GUIDs until I get one that starts with a letter, I'm wondering if there's an alternative UID type that either does not contain numbers or would otherwise meet this requirement.

Any thoughts?


Solution

  • If you just want to create a Guid that starts with a letter, you could do something like this:

    var b = Guid.NewGuid().ToByteArray();
    b[3] |= 0xF0;
    return new Guid(b);
    

    This will always generate a GUID that starts with the hex digit F.

    To create a Guid that doesn't contain any numbers you could use something like this:

    return new Guid(Guid.NewGuid().ToByteArray()
        .Select(b => (byte)(((b % 16) < 10 ? 0xA : b) | 
                            (((b >> 4) < 10 ? 0xA : (b >> 4)) << 4)))
        .ToArray());
    

    This will test each hex digit (two per byte) and coerce it to A if it's less than A.


    Both the above solutions generate real Guid objects, although the added restrictions do decrease the uniqueness of the resulting GUIDs to some degree (far more so in the second example). If you don't care about the output being actual GUIDs, you can simply remap the hex digits to something else and return the result a string, as others have suggested. FWIW, here's the shortest solution I can think of:

    return String.Concat(Guid.NewGuid().ToString("N").Select(c => (char)(c + 17)));
    

    This maps the hex digits 0 through 9 to the characters A through J, and the hex digits A - F to the characters r through w. It also generates a string without any hyphens. It For example:

    Before: e58d0f329a2f4615b922ecf53dcd090a
    After:  vFIuAwDCJrCwEGBFsJCCvtwFDutuAJAr
    

    Of course, you could convert this to all upper or lower case if you don't like the mixed case here.