Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[System.Guid] Discrepancy when constructing same Guid from string or byte array #29523

Closed
1ma opened this issue May 12, 2019 · 8 comments
Closed
Labels
area-System.Runtime documentation Documentation bug or enhancement, does not impact product or test code
Milestone

Comments

@1ma
Copy link

1ma commented May 12, 2019

I recently noticed that when you construct a Guid from a byte array you might not get the exact same Guid you described, as it happens when it is constructed from a string. In particular the 8 bytes in the higher groups seem to be flipped (9dad turns to ad9d, etc).

        [Fact]
        public void TestGuidDiscrepancy()
        {
            var asString = "6ba7b810-9dad-11d1-80b4-00c04fd430c8";
            var asBytes = new byte[]
            {
                0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1,
                0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8
            };

            var guid1 = new Guid(asString);
            var guid2 = new Guid(asBytes);

            Assert.Equal(guid1.ToString(), guid2.ToString());
        }
Uma.Uuid.Tests.GeneratorTest.TestGuidDiscrepancy

Assert.Equal() Failure
          ↓ (pos 0)
Expected: 6ba7b810-9dad-11d1-80b4-00c04fd430c8
Actual:   10b8a76b-ad9d-d111-80b4-00c04fd430c8
          ↑ (pos 0)
   at Uma.Uuid.Tests.GeneratorTest.TestGuidDiscrepancy() in GeneratorTest.cs:line 28

On the other hand, the 00000000-0000-0000-0000-000000000000 Guid passes the above test.

If this behaviour is correct I think that the documentation for the Guid(byte[]) method could be expanded a bit, explaining the relationship between Guid byte and string representation, and the algorithm to convert one form to the other.

Additional information:

$ dotnet --info
.NET Core SDK (reflecting any global.json):
 Version:   2.2.203
 Commit:    e5bab63eca

Runtime Environment:
 OS Name:     ubuntu
 OS Version:  16.04
 OS Platform: Linux
 RID:         ubuntu.16.04-x64
 Base Path:   /usr/share/dotnet/sdk/2.2.203/

Host (useful for support):
  Version: 2.2.4
  Commit:  f95848e524

.NET Core SDKs installed:
  2.2.203 [/usr/share/dotnet/sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.All 2.2.4 [/usr/share/dotnet/shared/Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.2.4 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.2.4 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
@Gnbrkm41
Copy link
Contributor

Gnbrkm41 commented May 12, 2019

the first 12 letters (00000000-0000) bit is in fact a 8-byte integer and 4-byte integer, not just 8 and 4 1-byte data I believe. Probably endianess thing.

@Gnbrkm41
Copy link
Contributor

e.g. 0x6b, 0xa7, 0xb8, 0x10 is 0x6BA7B810 when interpreted as integer on big-endian machines but 0x10B8A76b when interpreted as integer on little-endian machines. (i.e. x86-64 and ARM machines)

@Gnbrkm41
Copy link
Contributor

@Gnbrkm41
Copy link
Contributor

Gnbrkm41 commented May 12, 2019

Though, is there a standard on the endianess when interpreting GUID/UUIDs? that wikipedia article seem to state this:

The binary encoding of UUIDs varies between systems. Many systems encode the UUID entirely in a big-endian format.

But also:

...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.

assuming it's the latter case I think the behaviour is expected, however could it be useful to provide a way to interpret the GUIDs encoded in the former format?

@1ma
Copy link
Author

1ma commented May 12, 2019

Spot on, that's exactly what it's doing. Thanks!

I really believe this behavior should be more clearly mentioned[1] in the docs, because the string-based constructor interprets all the supported input formats as a whole big-endian bitstream, and the Guid(byte[]) one only states that the input must be A 16-element byte array containing values with which to initialize the GUID. You just don't expect it to work so differently, a remark and a few examples would be great.

[1] It is mentioned in the remarks of the Guid(Int32, Int16, Int16, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte) constructor, but in a rather vague way.

@danmoseley
Copy link
Member

@1ma perhaps you'd like to offer a PR for the docs? https://github.com/dotnet/dotnet-api-docs

@1ma
Copy link
Author

1ma commented May 12, 2019

I'll see if I can manage.

@bartonjs
Copy link
Member

Since the ctor is behaving as designed, and the proposed documentation update would be in a different repository, I'm going to go ahead and close this issue.

@msftgits msftgits transferred this issue from dotnet/corefx Feb 1, 2020
@msftgits msftgits added this to the 3.0 milestone Feb 1, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 13, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Runtime documentation Documentation bug or enhancement, does not impact product or test code
Projects
None yet
Development

No branches or pull requests

5 participants