4

When entering the following code into the C# immediate window, it yields some unusual results, which I can only assume are because internally, System.Guid flips certain bytes:

When using an ordinal byte array from 0 to 15

new Guid(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15})
[03020100-0504-0706-0809-0a0b0c0d0e0f]

When using a non-ordinal byte array with values 0 to 15

new Guid(new byte[] {3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11, 12, 13, 14, 15})
[00010203-0405-0607-0809-0a0b0c0d0e0f]

Why are the first 3 groups flipped?

Matthew Layton
  • 39,871
  • 52
  • 185
  • 313
  • Big endian, little endian. It is the way Intel designed their microprocessors that determine the byte order. Intel designed there micro's for speed and swapping byte order made the micros run faster. Microsoft just followed the Intel specification. – jdweng Aug 14 '17 at 09:36
  • Also see https://stackoverflow.com/questions/9195551/why-does-guid-tobytearray-order-the-bytes-the-way-it-does?rq=1 – schnaader Aug 15 '17 at 05:17

3 Answers3

7

Found on Wikipedia regarding UUID.

Other systems, notably Microsoft's marshalling of UUIDs in their COM/OLE libraries, use a mixed-endian format, whereby the first three components of the UUID are little-endian, and the last two are big-endian.

For example, 00112233-4455-6677-8899-aabbccddeeff is encoded as the bytes 33 22 11 00 55 44 77 66 88 99 aa bb cc dd ee ff

Community
  • 1
  • 1
Torbjörn Hansson
  • 18,354
  • 5
  • 33
  • 42
1

The first 4 byte block belong to an Int32 value, the next 2 blocks belong to Int16 values that are assigned to the Guid in reverse because of byte order. Perhaps you should try the other constructor that has matching integer data types as parameters and gives a more intuitive ordering:

Guid g = new Guid(0xA, 0xB, 0xC, 
                  new Byte[] { 0, 1, 2, 3, 4, 5, 6, 7 } );
Console.WriteLine("{0:B}", g);
// The example displays the following output:
//        {0000000a-000b-000c-0001-020304050607}
schnaader
  • 49,103
  • 10
  • 104
  • 136
1

Look at the source code of Guid.cs to see the structure behind it:

// Represents a Globally Unique Identifier.
public struct Guid : IFormattable, IComparable,
                     IComparable<Guid>, IEquatable<Guid> {
    //  Member variables
    private int         _a; // <<== First group,  4 bytes
    private short       _b; // <<== Second group, 2 bytes
    private short       _c; // <<== Third group,  2 bytes
    private byte       _d;
    private byte       _e;
    private byte       _f;
    private byte       _g;
    private byte       _h;
    private byte       _i;
    private byte       _j;
    private byte       _k;
    ...
}

As you can see, internally Guid consists of a 32-bit integer, two 16-bit integers, and 8 individual bytes. On little-endian architectures the bytes of the first int and two shorts that follow it are stored in reverse order. The order of the remaining eight bytes remains unchanged.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523