增加C#中的Guid

我有一个具有guid变量的应用程序,该变量需要是唯一的(当然)。 我知道统计上任何guid都应该被认为是唯一的,但是由于开发/测试环境的原因,可以多次看到相同的值。 所以当发生这种情况时,我想“增加”Guid的值,而不是仅仅创建一个全新的值。 似乎没有一种简单的方法可以做到这一点。 我找到了一个黑客,我将发布一个可能的答案,但想要一个更清洁的解决方案。

你可以得到guid的字节组件,所以你可以解决这个问题:

 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); } } 

编辑:现在正确的字节顺序

感谢Thomas Levesque的字节顺序,这里有一个漂亮的LINQ实现:

 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]); } 

请注意,如果你设法将它增加到那么远,它将包装到Guid.Empty

如果你继续增加单个bytes副本而不是依次调用每个GUID上的ToByteArray会更有效。

已validation的有序字符串解决方案:

  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..."); } 

validation:

  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); } } } 

可能的解决方案 – 我认为这有效(未经过实际测试),但需要更好的解决方案。

 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); } 

编辑:这是我最终使用的代码; 对于一般技术的上述答案的道具,虽然没有“未经检查”的条款,它们都会在某些情况下抛出exception。 但我也尝试使下面的内容尽可能可读。

 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; }