I have an application that has a guid variable which needs to be unique (of course). I know that statistically any guid should just be assumed to be unique, but due to dev/test environment reasons, the same value may be seen multiple times. So when that happens, I want to "increment" the value of the Guid, rather than just creating a whole new one. There does not seem to be a simple way to do this. I found a hack, which I will post as a possible answer, but want a cleaner solution.
-
Why can't it be a new Guid? – a-ctor May 22 '15 at 20:01
-
7That's *not* how `GUID`s are *supposed to be* handled. What is wrong with calling `Guid.NewGuid()` when you need a new one? – Der Kommissar May 22 '15 at 20:01
-
The way you are using this, you might want to consider calling it a UUID instead. – VoidStar May 22 '15 at 20:05
-
Aren't you looking for a sequential GUID: http://stackoverflow.com/questions/1752004/sequential-guid-generator-c-sharp ? – atlaste May 22 '15 at 20:05
-
1@EBrown the main problem with non-sequential GUID's is that they don't work well with b-trees used in databases. More exact: they drain the performance from the system. Also, IIRC sequential GUID's are perfectly valid GUID's if you use the correct implementation... but to be honest I'm not 100% sure (can't remember the details from the spec). – atlaste May 22 '15 at 20:06
-
Yes, looked it up. Sequential GUID's are normally implemented as type 1 UUID's from the spec: http://tools.ietf.org/rfc/rfc4122.txt . – atlaste May 22 '15 at 20:09
-
@EBrown As I explained in the question, I want to increment when there is a collision. This log is for humans to see, so the human could see that the guids were nearly identical, and the database is satisfied that they are unique. – Abacus Jul 31 '15 at 19:07
-
@atlaste No, the original guid is generated randomly, and the point is address when a collision occurs, by creating a nearly identical value that is also unique. – Abacus Jul 31 '15 at 19:08
-
2@Abacus so basically you want a Global unique sequential IDs. Well it is possible, since Google does that using timestamps in Spanner -- but they have dedicated hardware for that (including stuff like geo locators and atom clocks and so on, it's quite a fancy paper to read :-). For normal people like me and probably you, it's just not going to happen with the "Global Unique" constraint. If you drop that constraint, might as well use a sequencer, since they are designed to do this. – atlaste Jul 31 '15 at 20:12
4 Answers
You can get the byte components of the guid, so you can just work on that:
static class GuidExtensions
{
private static readonly int[] _guidByteOrder =
new[] { 15, 14, 13, 12, 11, 10, 9, 8, 6, 7, 4, 5, 0, 1, 2, 3 };
public static Guid Increment(this Guid guid)
{
var bytes = guid.ToByteArray();
bool carry = true;
for (int i = 0; i < _guidByteOrder.Length && carry; i++)
{
int index = _guidByteOrder[i];
byte oldValue = bytes[index]++;
carry = oldValue > bytes[index];
}
return new Guid(bytes);
}
}
EDIT: now with correct byte order

- 286,951
- 70
- 623
- 758
-
1Why the downvotes? care to explain what's wrong with this answer? – Thomas Levesque May 22 '15 at 20:12
-
This code throws an OverflowException with the ++ when the byte's value is 255. So would need to have unchecked{} around that statement. – Abacus Jul 31 '15 at 16:33
-
@Abacus, is your project compiled with the `/checked` option? Integer arithmetic is unchecked with the default options. – Thomas Levesque Jul 31 '15 at 23:37
-
Yes, it is checked in my project. Or rather, it is not unchecked. Using VS2010 Premium, and it's under project properties, Compile, Advanced, and I have "Remove integer overflow checks" left unchecked. This seems the sensible default -- it seems very strange to me that the default behavior would be unchecked. – Abacus Sep 01 '15 at 16:08
Thanks to Thomas Levesque's byte order, here's a nifty LINQ implementation:
static int[] byteOrder = { 15, 14, 13, 12, 11, 10, 9, 8, 6, 7, 4, 5, 0, 1, 2, 3 };
static Guid NextGuid(Guid guid)
{
var bytes = guid.ToByteArray();
var canIncrement = byteOrder.Any(i => ++bytes[i] != 0);
return new Guid(canIncrement ? bytes : new byte[16]);
}
Note it wraps around to Guid.Empty
if you manage to increment it that far.
It would be more efficient if you were to keep incrementing a single copy of bytes
rather than calling ToByteArray
on each GUID in turn.
-
-
-
I observed this order: 15, 14, 13, 12, 11, 10, 9, 8, 6, 7, 4, 5, 0, 1, 2, 3 – Thomas Levesque May 22 '15 at 20:17
-
@ThomasLevesque You're right, mine was all over the place and I didn't actually check any of the higher bytes... Thanks – Rawling May 22 '15 at 20:19
-
@ThomasLevesque I've now checked and I'm pretty sure you're right, so thanks again. – Rawling May 22 '15 at 20:24
-
This code throws an OverflowException with the ++ when the byte's value is 255. So would need to have unchecked{} around that statement. – Abacus Jul 31 '15 at 16:34
-
1@Abacus Well, that depends whether you're running in a `checked` context or not. The VS default is not, so I didn't bother. – Rawling Jul 31 '15 at 17:53
-
1My pair-coding partner and I just want to acknowledge how awesome that .Any() is. Very cool. – David Bond Jul 24 '20 at 09:29
Possible solution -- I think this works (not really tested), but want a better solution.
public static Guid Increment(this Guid value)
{
var bytes = value.ToByteArray();
// Note that the order of bytes in the returned byte array is different from the string representation of a Guid value.
// Guid: 00112233-4455-6677-8899-aabbccddeeff
// byte array: 33 22 11 00 55 44 77 66 88 99 AA BB CC DD EE FF
// So the byte order of the following indexes indicates the true low-to-high sequence
if (++bytes[15] == 0) if (++bytes[14] == 0) if (++bytes[13] == 0) if (++bytes[12] == 0) if (++bytes[11] == 0) if (++bytes[10] == 0) // normal order
if (++bytes[9] == 0) if (++bytes[8] == 0) // normal order
if (++bytes[6] == 0) if (++bytes[7] == 0) // reverse order
if (++bytes[5] == 0) if (++bytes[4] == 0) // reverse order
if (++bytes[3] == 0) if (++bytes[2] == 0) if (++bytes[1] == 0) { ++bytes[0]; } // reverse order
return new Guid(bytes);
}
Edit: here is the code I ended up using; props to the answers above for the general technique, although without the "unchecked" clause they both would throw exceptions in some cases. But I also tried to make the below as readable as possible.
private static int[] _guidByteOrder = { 15, 14, 13, 12, 11, 10, 9, 8, 6, 7, 4, 5, 0, 1, 2, 3 };
public static Guid NextGuid(this Guid guid)
{
var bytes = guid.ToByteArray();
for (int i = 0; i < 16; i++)
{
var iByte = _guidByteOrder[i];
unchecked { bytes[iByte] += 1; }
if (bytes[iByte] != 0)
return new Guid(bytes);
}
return Guid.Empty;
}

- 2,041
- 1
- 18
- 23
-
5
-
2Using `BigInteger` to increment will lead to obviously correct and likely nice looking code. – Alexei Levenkov May 22 '15 at 20:09
Verified Solution for Ordered Strings:
private static Guid Increment(Guid guid)
{
byte[] bytes = guid.ToByteArray();
byte[] order = { 15, 14, 13, 12, 11, 10, 9, 8, 6, 7, 4, 5, 0, 1, 2, 3 };
for (int i = 0; i < 16; i++)
{
if (bytes[order[i]] == byte.MaxValue)
{
bytes[order[i]] = 0;
}
else
{
bytes[order[i]]++;
return new Guid(bytes);
}
}
throw new OverflowException("Congratulations you are one in a billion billion billion billion etc...");
}
Verification:
private static Guid IncrementProof(Guid guid, int start, int end)
{
byte[] bytes = guid.ToByteArray();
byte[] order = { 15, 14, 13, 12, 11, 10, 9, 8, 6, 7, 4, 5, 0, 1, 2, 3 };
for (int i = start; i < end; i++)
{
if (bytes[order[i]] == byte.MaxValue)
{
bytes[order[i]] = 0;
}
else
{
bytes[order[i]]++;
return new Guid(bytes);
}
}
throw new OverflowException("Congratulations you are one in a billion billion billion billion etc...");
}
static void Main(string[] args)
{
Guid temp = new Guid();
for (int j = 0; j < 16; j++)
{
for (int i = 0; i < 255; i++)
{
Console.WriteLine(temp.ToString());
temp = IncrementProof(temp, j, j + 1);
}
}
}

- 11
- 2