Add net9 Guid.Variant and Guid.Version - #604
Merged
Merged
Conversation
Two instance properties. Guid.AllBitsSet and CreateVersion7, the other net9 additions, were already polyfilled, so this closes the type. Both are the high nibble of one byte of the little endian layout ToByteArray produces: the version at index 7 and the variant at index 8. Derived empirically rather than from the RFC, and verified exhaustively over all 65536 combinations of those two bytes, plus 500000 random guids to confirm the other fourteen bytes do not participate. Variant is worth knowing about: it is the raw four bit nibble, not the RFC 4122 variant field, which is only the top two bits. So an ordinary uuid reports 8, 9, 10 or 11 rather than one fixed value. A test asserting a single value failed identically on net11, which is what identified this as a wrong expectation rather than a broken polyfill. Reads through TryWriteBytes into a stack buffer where that exists, from netcoreapp2.1 and netstandard2.1, and falls back to ToByteArray on net461 and netstandard2.0. API count 1153 -> 1155.
This was referenced Sep 10, 2026
This was referenced Sep 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two instance properties, both net9. The shortlist named only
Variant, butVersionarrived with it and is the natural pair.Guid.AllBitsSetandCreateVersion7, the other net9 additions, were already polyfilled — so this closes the type.Derived empirically, not from the RFC
Both are the high nibble of a single byte of the little-endian layout
ToByteArrayproduces: the version at index 7 and the variant at index 8. Index 7 rather than 6 is the part worth checking rather than assuming, because the third group of a GUID is stored little-endian, so the version nibble that appears first in the text form lands in the second byte of that field.Verified exhaustively: all 65 536 combinations of bytes 7 and 8 agree with the BCL, plus 500 000 random GUIDs confirming the other fourteen bytes do not participate. The tests also cross-check against the canonical string form — reading the version and variant nibbles straight out of
ToString("D")— which is the assertion that would catch a wrong index or a wrong-endianness read, independently of how the implementation gets there.Variantis not the RFC 4122 variant fieldWorth flagging, because it is genuinely surprising.
Guid.Variantreturns the raw four-bit nibble, whereas the RFC 4122 variant is only the top two bits. So an ordinary UUID does not report a single constant — it reports 8, 9, 10 or 11 depending on the two "don't care" bits underneath:6ba7b810-9dad-11d1-80b4-00c04fd430c83d813cbb-47fb-32ba-91df-831e1593ac2901890a5d-ac96-774b-bcce-b302099a8057Guid.EmptyI got this wrong first time: a test asserting
Guid.NewGuid().Variant == 8failed on net11 as well as on the polyfill, which is what identified it as a bad expectation rather than a broken implementation. The test now asserts the RFC 4122 predicate (Variant & 0b1100 == 0b1000) over 2000 generated GUIDs, which is what a caller actually wants to check.Incidentally that also cross-checks Polyfill's own
CreateVersion7: it passes on net462, so the existing polyfill is setting the variant bits correctly.Implementation
Reads through
TryWriteBytesinto a stack buffer where that exists — from netcoreapp2.1 and netstandard2.1 — and falls back toToByteArray()on net461 and netstandard2.0, which is the only path that allocates. No//Note:needed: on the frameworks where an allocation-free read is possible, the polyfill does it.Verification
Solution clean in Release, Consume clean across all 22 TFMs, tests green on net11.0 (1735), net10.0 (1735), net9.0 (1735), net8.0 (1732), net462 (1681), plus PublicTests, EmbeddedTests, UnsafeTests, NoRefsTests and NoExtrasTests. net8.0 and net462 cover the two different read paths.
API count 1153 → 1155.