Skip to content

CkUuid

Job: read a UUID from any way people write it, and hand it back in the one spelling you can store, compare and derive from.

A UUID (universally unique identifier — .NET calls the type Guid) is a 128-bit identifier written as 32 hex digits, like 08d3f9c6-5e4a-4b8f-9d2e-7a1b3c5d7e9f. The trouble is that systems spell the same identifier many ways: with hyphens, without them, wrapped in braces or parentheses, prefixed with urn:uuid:, in either casing. CkUuid reads all of those — plus a boxed Guid straight off a database reader — and writes back the lowercase hyphenated form, so two spellings of one identifier always match. One rule matters most here: there is no substitute fallback. An identifier names one specific thing, and an invented one is worse than none — it corrupts deduplication and audit trails. A value that cannot be used answers "" (string methods) or Guid.Empty (the all-zeros Guid), and the all-zeros UUID itself counts as missing by default, because that is what databases and serializers emit when nobody set a value.

Quick look

using SafeCoder.CommonKit;

CkUuid.Canonical("{08D3F9C6-5E4A-4B8F-9D2E-7A1B3C5D7E9F}");     // -> "08d3f9c6-5e4a-4b8f-9d2e-7a1b3c5d7e9f"
CkUuid.ToGuid("junk");                                          // -> Guid.Empty  (rejected)
CkUuid.ToGuidOrNull("00000000-0000-0000-0000-000000000000");    // -> null  (all zeros = missing)
CkUuid.Version("08d3f9c6-5e4a-4b8f-9d2e-7a1b3c5d7e9f");         // -> 4
CkUuid.IsUuid("junk");                                          // -> false
CkUuid.SameUuid("{08D3F9C6-5E4A-4B8F-9D2E-7A1B3C5D7E9F}", "08d3f9c65e4a4b8f9d2e7a1b3c5d7e9f");   // -> true
CkUuid.IsVersion("08d3f9c6-5e4a-4b8f-9d2e-7a1b3c5d7e9f", 4, 7); // -> true
Guid id = CkUuid.NewV7();        // sorts by creation time
CkUuid.Explain("junk");          // -> "not a UUID in a known shape"

Methods

Canonical

The one agreed spelling.

string Canonical(
    object? input = null,
    bool treatZerosAsMissing = true,
    bool throwIfInvalid = CkSettings.DefaultThrowIfInvalid
)
Parameter Type Default What it does
input object? null The value: text in any everyday shape, or a boxed Guid.
treatZerosAsMissing bool true Counts the all-zeros UUID as missing rather than real. Pass false to read it as a real value.
throwIfInvalid bool CkSettings.DefaultThrowIfInvalid (false) Pass true to throw a CkUuidException that says why, instead of answering "", when the value cannot be used.

Returns

When Default With throwIfInvalid: true
The value is a UUID in any supported shape The canonical text: "08d3f9c6-5e4a-4b8f-9d2e-7a1b3c5d7e9f" The canonical text: "08d3f9c6-5e4a-4b8f-9d2e-7a1b3c5d7e9f"
Rejected: missing, oversized, not a UUID in a known shape, or — by default — all zeros Empty string Throws CkUuidException — carries Input, Expected and Reason

There is deliberately no substitute fallback — an invented identifier is worse than an empty one.

Reads a UUID from any supported shape and writes it lowercase, hyphenated, no braces — the form to store and compare.

CkUuid.Canonical("{08D3F9C6-5E4A-4B8F-9D2E-7A1B3C5D7E9F}");         // -> "08d3f9c6-5e4a-4b8f-9d2e-7a1b3c5d7e9f"
CkUuid.Canonical("08d3f9c65e4a4b8f9d2e7a1b3c5d7e9f");               // -> "08d3f9c6-5e4a-4b8f-9d2e-7a1b3c5d7e9f"
CkUuid.Canonical("urn:uuid:08d3f9c6-5e4a-4b8f-9d2e-7a1b3c5d7e9f");  // -> "08d3f9c6-5e4a-4b8f-9d2e-7a1b3c5d7e9f"
CkUuid.Canonical("00000000-0000-0000-0000-000000000000");           // -> ""  (zeros mean missing)
CkUuid.Canonical("not an id");                                      // -> ""  (rejected)

Format

One of the four everyday shapes.

string Format(
    object? input = null,
    string? into = "D",
    bool treatZerosAsMissing = true,
    bool throwIfInvalid = CkSettings.DefaultThrowIfInvalid
)
Parameter Type Default What it does
input object? null The value: text in any everyday shape, or a boxed Guid.
into string? "D" The shape to write: "D" hyphenated, "N" 32 bare digits, "B" braced, "P" parenthesized — always lowercase. Anything else is rejected.
treatZerosAsMissing bool true Counts the all-zeros UUID as missing rather than real. Pass false to read it as a real value.
throwIfInvalid bool CkSettings.DefaultThrowIfInvalid (false) Pass true to throw a CkUuidException that says why, instead of answering "", when the value or the shape cannot be used.

Returns

When Default With throwIfInvalid: true
The value is a UUID and into is one of the four shapes The formatted text: "08d3f9c65e4a4b8f9d2e7a1b3c5d7e9f" with into: "N" The formatted text: "08d3f9c65e4a4b8f9d2e7a1b3c5d7e9f" with into: "N"
Rejected: a bad value, or a shape that is not D, N, B or P Empty string Throws CkUuidException — carries Input, Expected and Reason

The value itself is read the way Canonical reads one.

For systems that store one of the other spellings. The into parameter names the shape: "D" hyphenated (the default), "N" 32 bare digits, "B" braced, "P" parenthesized — always lowercase.

CkUuid.Format(
    input: "08d3f9c6-5e4a-4b8f-9d2e-7a1b3c5d7e9f",
    into: "D"
);   // -> "08d3f9c6-5e4a-4b8f-9d2e-7a1b3c5d7e9f"

CkUuid.Format(
    input: "08d3f9c6-5e4a-4b8f-9d2e-7a1b3c5d7e9f",
    into: "N"
);   // -> "08d3f9c65e4a4b8f9d2e7a1b3c5d7e9f"

CkUuid.Format(
    input: "08d3f9c6-5e4a-4b8f-9d2e-7a1b3c5d7e9f",
    into: "B"
);   // -> "{08d3f9c6-5e4a-4b8f-9d2e-7a1b3c5d7e9f}"

CkUuid.Format(
    input: "08d3f9c6-5e4a-4b8f-9d2e-7a1b3c5d7e9f",
    into: "P"
);   // -> "(08d3f9c6-5e4a-4b8f-9d2e-7a1b3c5d7e9f)"

The two typed readers, ToGuid and ToGuidOrNull, both take treatZerosAsMissing (default true). Switch it off only when the all-zeros value really means something in your data:

CkUuid.ToGuidOrNull(
    input: "00000000-0000-0000-0000-000000000000",
    treatZerosAsMissing: false
);   // -> Guid.Empty, read as a real value

ToGuid

The typed reader.

Guid ToGuid(
    object? input = null,
    bool treatZerosAsMissing = true,
    bool throwIfInvalid = CkSettings.DefaultThrowIfInvalid
)
Parameter Type Default What it does
input object? null The value: text in any everyday shape, or a boxed Guid.
treatZerosAsMissing bool true Counts the all-zeros UUID as missing rather than real. Pass false to read it as a real value — and lose the unambiguous sentinel.
throwIfInvalid bool CkSettings.DefaultThrowIfInvalid (false) Pass true to throw a CkUuidException that says why, instead of answering Guid.Empty, when the value cannot be used.

Returns

When Default With throwIfInvalid: true
The value is a UUID in any supported shape The Guid 08d3f9c6-5e4a-4b8f-9d2e-7a1b3c5d7e9f The Guid 08d3f9c6-5e4a-4b8f-9d2e-7a1b3c5d7e9f
Rejected: missing, oversized, not a UUID in a known shape, or — by default — all zeros Guid.Empty Throws CkUuidException — carries Input, Expected and Reason

No fallback parameter, on purpose — rejection is always Guid.Empty, never a made-up id.

ToGuid reads the same shapes but answers a Guid — for Entity Framework keys, dictionary lookups and comparisons.

CkUuid.ToGuid("{08D3F9C6-5E4A-4B8F-9D2E-7A1B3C5D7E9F}");        // -> the Guid 08d3f9c6-5e4a-4b8f-9d2e-7a1b3c5d7e9f
CkUuid.ToGuid("junk");                                          // -> Guid.Empty  (rejected)

ToGuidOrNull

Null when there is nothing usable.

Guid? ToGuidOrNull(
    object? input = null,
    bool treatZerosAsMissing = true
)
Parameter Type Default What it does
input object? null The value: text in any everyday shape, or a boxed Guid.
treatZerosAsMissing bool true Reads the all-zeros UUID as missing, so it comes back as null too. Pass false to hand it back as Guid.Empty.

Returns

When You get
The value is a UUID in any supported shape The Guid 08d3f9c6-5e4a-4b8f-9d2e-7a1b3c5d7e9f
Missing, unreadable, or a sentinel: null, DBNull, "junk", an unsupported type, or — by default — the all-zeros UUID null — this method never throws

An honest nothing is never an error, and neither is anything else — null is the answer for whatever cannot be used.

Works like ToGuid but answers null instead when there is nothing usable: a missing value (null or DBNull), one that cannot be read, or — by default — the all-zeros UUID. That way a nullable database column receives NULL rather than an empty GUID, and is null replaces comparing against the sentinel.

CkUuid.ToGuidOrNull("junk");                                    // -> null
CkUuid.ToGuidOrNull(null);                                      // -> null  (nothing there — an honest answer)
CkUuid.ToGuidOrNull("00000000-0000-0000-0000-000000000000");    // -> null  (zeros mean missing)

FromName

The same UUID from the same name, every time.

Guid FromName(
    object? name = null,
    object? space = null,
    int version = 5,
    bool throwIfInvalid = CkSettings.DefaultThrowIfInvalid
)
Parameter Type Default What it does
name object? null The name to derive from: text, or a whole number written invariantly. At most CkSettings.MaxUuidNameLength (1,024) characters — over that is rejected, never truncated.
space object? null The name-space UUID, in any shape Canonical reads — one of the RFC spaces (NamespaceDns, NamespaceUrl…) or, better for your own ids, one minted once per id family.
version int 5 5 (SHA-1, recommended) or 3 (MD5, legacy interop only). Anything else is rejected.
throwIfInvalid bool CkSettings.DefaultThrowIfInvalid (false) Pass true to throw a CkUuidException that says why, instead of answering Guid.Empty, when a value cannot be used.

Returns

When Default With throwIfInvalid: true
The name and name space are usable The derived Guid: 2ed6657d-e927-568b-95e1-2665a8aea6a2 for "www.example.com" in NamespaceDns The derived Guid: 2ed6657d-e927-568b-95e1-2665a8aea6a2 for "www.example.com" in NamespaceDns
Rejected: a missing or oversized name, a name space that cannot be read, or a version other than 5 and 3 Guid.Empty Throws CkUuidException — carries Input, Expected and Reason

A bad ingredient never derives a wrong id — it is rejected instead.

Derives a name-based UUID from two ingredients: a name space (itself a UUID, marking which family of ids you are in) and a name. The derivation is deterministic — the same name space and name always give the same UUID, on every platform and in every language. That is the point: an identifier can be computed instead of stored. "Which event UUID belongs to claim 12345" needs no mapping table — derive it again and you get the same answer, which also makes retries and reruns safe, since the same occurrence always produces the same id.

The default is version 5, which hashes with SHA-1 (a hash is a fixed-size fingerprint computed from data); pass version: 3 for MD5, only when you must match a system that already derives with it. The class ships the RFC 9562 name spaces — NamespaceDns, NamespaceUrl, NamespaceOid, NamespaceX500 — but for your own ids it is better to mint one fresh UUID per id family, once, and hard-code it.

CkUuid.FromName(
    name: "www.example.com",
    space: CkUuid.NamespaceDns
);   // -> the Guid 2ed6657d-e927-568b-95e1-2665a8aea6a2 — here, in Python, everywhere

CkUuid.FromName(
    name: "www.example.com",
    space: CkUuid.NamespaceDns,
    version: 3
);   // -> the Guid 5df41881-3aed-3515-88a7-2f4a814cf09e  (the MD5 variant)

The name is hashed exactly as given, byte for byte — no trimming, no case-folding — because a derived identifier must match what every other system derives from the same name. A whole number works as a name too (written invariantly), and a name over 1,024 characters is rejected rather than truncated, since truncating would change the id.

Version

Which kind of UUID this is.

int Version(
    object? input = null,
    int fallback = 0,
    bool throwIfInvalid = CkSettings.DefaultThrowIfInvalid
)
Parameter Type Default What it does
input object? null The value: text in any everyday shape, or a boxed Guid.
fallback int 0 What comes back when the value cannot be used — 0 by default, which no version is.
throwIfInvalid bool CkSettings.DefaultThrowIfInvalid (false) Pass true to throw a CkUuidException that says why, instead of answering the fallback, when the value cannot be used.

Returns

When Default With throwIfInvalid: true
The value is a UUID The version digit: 4 The version digit: 4
Rejected: missing, not a UUID in a known shape, or all zeros — always missing here The fallback (default 0) Throws CkUuidException — carries Input, Expected and Reason

The one method with a fallback parameter — it answers a plain int, not an identity.

Reads the UUID's version digit: 4 is random, 5 and 3 are name-based, 7 is time-ordered, 1 is the classic time-and-MAC kind.

CkUuid.Version("08d3f9c6-5e4a-4b8f-9d2e-7a1b3c5d7e9f");   // -> 4  (random)

Guid derived = CkUuid.FromName(
    name: "www.example.com",
    space: CkUuid.NamespaceDns
);
CkUuid.Version(derived);                                  // -> 5  (name-based)

CkUuid.Version("junk");                                   // -> 0  (the default fallback)

IsUuid

Does it read as a UUID at all?

bool IsUuid(
    object? input = null,
    bool treatZerosAsMissing = true,
    bool throwIfInvalid = CkSettings.DefaultThrowIfInvalid
)
Parameter Type Default What it does
input object? null The value: text in any everyday shape, or a boxed Guid.
treatZerosAsMissing bool true Counts the all-zeros UUID as missing rather than real.
throwIfInvalid bool CkSettings.DefaultThrowIfInvalid (false) Pass true to throw a CkUuidException that says why, instead of answering false, when the value is not a UUID.

Returns

When Default With throwIfInvalid: true
The value reads as a UUID under the readers' rules true true
Rejected: missing, not a UUID in a known shape, a wrong type, or all zeros with the default on false Throws CkUuidException — carries Input, Expected and Reason

The yes-or-no form of Canonical and ToGuid: the four text shapes, the urn:uuid: prefix, any casing, a boxed Guid. When the value is going to be stored, read it with ToGuidOrNull instead and check for null — same question, and you get the value back.

CkUuid.IsUuid("{08D3F9C6-5E4A-4B8F-9D2E-7A1B3C5D7E9F}");   // -> true
CkUuid.IsUuid("00000000-0000-0000-0000-000000000000");     // -> false  (missing by default)
CkUuid.IsUuid("junk");                                     // -> false

IsNil

Is it the all-zeros UUID?

bool IsNil(
    object? input = null,
    bool throwIfInvalid = CkSettings.DefaultThrowIfInvalid
)
Parameter Type Default What it does
input object? null The value: text in any everyday shape, or a boxed Guid.
throwIfInvalid bool CkSettings.DefaultThrowIfInvalid (false) Pass true to throw a CkUuidException that says why, instead of answering false, when the value is not a UUID.

Returns

When Default With throwIfInvalid: true
The value reads as a UUID and is 00000000-0000-0000-0000-000000000000 true true
Any other UUID false false
Rejected: not a UUID false Throws CkUuidException — carries Input, Expected and Reason

RFC 9562 calls it the nil UUID; it is what databases and serializers emit when nobody set a value, the 1900-01-01 of identifiers. The readers turn it into "missing" silently; this method says so out loud, for data-quality checks and for telling "nobody set it" from "not an id". The same job CkDate.IsPlaceholder does for dates.

CkUuid.IsNil("00000000-0000-0000-0000-000000000000");   // -> true
CkUuid.IsNil(Guid.Empty);                                // -> true
CkUuid.IsNil("junk");                                    // -> false  (not a UUID at all)

IsCanonical

Is it written in the canonical spelling?

bool IsCanonical(
    object? input = null,
    bool throwIfInvalid = CkSettings.DefaultThrowIfInvalid
)
Parameter Type Default What it does
input object? null The raw value.
throwIfInvalid bool CkSettings.DefaultThrowIfInvalid (false) Pass true to throw a CkUuidException that says why, instead of answering false, when the value is not canonical UUID text.

Returns

When Default With throwIfInvalid: true
Text that is exactly the lowercase, hyphenated, 36-character form true true
A UUID in another dressing — braces, bare digits, upper case, urn:uuid: — or a boxed Guid false Throws — the reason says it is a UUID in another form
Rejected: not a UUID at all false Throws CkUuidException — carries Input, Expected and Reason

A shape check for API contracts and columns that must hold canonical text, the same idea as CkCountry.IsAlpha2. Surrounding whitespace and markup are cleaned away first; then the spelling must be exactly what Canonical would write. The all-zeros UUID is canonical-shaped, so true here — whether it means anything is IsUuid's question. To accept any shape and store the canonical spelling, read the value with Canonical instead.

CkUuid.IsCanonical("08d3f9c6-5e4a-4b8f-9d2e-7a1b3c5d7e9f");     // -> true
CkUuid.IsCanonical("08D3F9C6-5E4A-4B8F-9D2E-7A1B3C5D7E9F");     // -> false  (upper case)
CkUuid.IsCanonical("{08d3f9c6-5e4a-4b8f-9d2e-7a1b3c5d7e9f}");   // -> false  (braces)

IsStandard

Is it an RFC 9562 UUID?

bool IsStandard(
    object? input = null,
    bool throwIfInvalid = CkSettings.DefaultThrowIfInvalid
)
Parameter Type Default What it does
input object? null The value: text in any everyday shape, or a boxed Guid.
throwIfInvalid bool CkSettings.DefaultThrowIfInvalid (false) Pass true to throw a CkUuidException that says why, instead of answering false, when the value is not a UUID.

Returns

When Default With throwIfInvalid: true
The value reads as a UUID whose variant bits are the standard 10xx true true
Another variant: the legacy Microsoft or NCS layouts, the reserved variant, all ones false false
Rejected: not a UUID, or all zeros — always missing here false Throws CkUuidException — carries Input, Expected and Reason

The variant is what makes the Version digit meaningful: Version reads the digit as written, and a random sixteen bytes dressed as a UUID has one too. Pair the two when an id must be a real RFC 9562 UUID of a given kind.

CkUuid.IsStandard("08d3f9c6-5e4a-4b8f-9d2e-7a1b3c5d7e9f");   // -> true   (variant 9)
CkUuid.IsStandard("08d3f9c6-5e4a-4b8f-cd2e-7a1b3c5d7e9f");   // -> false  (variant c: the Microsoft layout)
CkUuid.IsStandard(Guid.NewGuid());                            // -> true

IsVersion

Is it one of these kinds?

bool IsVersion(
    object? input = null,
    params IEnumerable<int> versions
)
Parameter Type Default What it does
input object? null The value: text in any everyday shape, or a boxed Guid.
versions params IEnumerable<int> — The version digits to accept, 1 to 8.

Returns

When You get
The value reads as a UUID and its version digit is listed true
It is not a UUID, the digit is not listed, the list is empty, or the value is all zeros false — an answer, not a failure; it never throws

For "random or time-ordered ids only": IsVersion(id, 4, 7). Read the way Version reads it — the digit as written, zeros always missing. A params list must be last, so there is no throwIfInvalid; call Version with it first when you need the exception. Pair with IsStandard when the digit must be meaningful.

CkUuid.IsVersion("08d3f9c6-5e4a-4b8f-9d2e-7a1b3c5d7e9f", 4, 7);   // -> true
CkUuid.IsVersion("2ed6657d-e927-568b-95e1-2665a8aea6a2", 4, 7);   // -> false  (a v5)

IsFromName

Does this id still match its natural key?

bool IsFromName(
    object? input = null,
    object? name = null,
    object? space = null,
    int version = 5,
    bool throwIfInvalid = CkSettings.DefaultThrowIfInvalid
)
Parameter Type Default What it does
input object? null The UUID to check: text in any everyday shape, or a boxed Guid.
name object? null The name to derive from: text, or a whole number written invariantly. Hashed exactly as given.
space object? null The name space UUID, in any shape Canonical reads.
version int 5 5 (SHA-1) or 3 (MD5), matching how the id was derived.
throwIfInvalid bool CkSettings.DefaultThrowIfInvalid (false) Pass true to throw a CkUuidException that says which part cannot be used and why, instead of answering false.

Returns

When Default With throwIfInvalid: true
The value reads as a UUID and equals the one FromName derives true true
It reads, and is a different UUID false false
Rejected: the value is not a UUID, or the name, space or version cannot be used false Throws CkUuidException — carries Input, Expected and Reason

FromName(name, space) == ToGuid(input) as one call, with the same rules on every part: the name is never cleaned, so " claim-1 " and "claim-1" derive different ids. For verifying a stored id against the record's natural key, and for checking that another system derived the id the same way.

CkUuid.IsFromName(
    input: "2ed6657d-e927-568b-95e1-2665a8aea6a2",
    name: "www.example.com",
    space: CkUuid.NamespaceDns
);   // -> true
CkUuid.IsFromName(
    input: "2ed6657d-e927-568b-95e1-2665a8aea6a2",
    name: "WWW.EXAMPLE.COM",
    space: CkUuid.NamespaceDns
);   // -> false  (the name is hashed as given)

SameUuid

The same id, whatever the dressing?

bool SameUuid(
    object? a = null,
    object? b = null,
    bool treatZerosAsMissing = true,
    bool throwIfInvalid = CkSettings.DefaultThrowIfInvalid
)
Parameter Type Default What it does
a object? null The first value: text in any shape, or a boxed Guid.
b object? null The second value, read the same way.
treatZerosAsMissing bool true Counts the all-zeros UUID as missing, so two missing ids are not the same id. Switch it off to let two nil values match.
throwIfInvalid bool CkSettings.DefaultThrowIfInvalid (false) Pass true to throw a CkUuidException that says which value is not a UUID and why, instead of answering false.

Returns

When Default With throwIfInvalid: true
Both read as UUIDs and are equal true true
Both read, and differ false false
Rejected: either value is not a UUID false Throws CkUuidException — carries Input, Expected and Reason

{08D3F9C6-…} from a SQL Server tool, the bare digits from a URL and a boxed Guid off a reader all match one another. Two values that are not UUIDs are never the same — two rejected values are two unknowns, not one identity — and by default neither are two nil values, since missing is not an identity.

CkUuid.SameUuid("{08D3F9C6-5E4A-4B8F-9D2E-7A1B3C5D7E9F}", "08d3f9c65e4a4b8f9d2e7a1b3c5d7e9f");   // -> true
CkUuid.SameUuid(Guid.Empty, "00000000-0000-0000-0000-000000000000");                            // -> false  (two missing)

NewV7

An id that sorts by time.

Guid NewV7(
    object? at = null,
    bool throwIfInvalid = CkSettings.DefaultThrowIfInvalid
)
Parameter Type Default What it does
at object? null The moment to stamp, read as CkDateTime.ToDateTime reads one; null for now.
throwIfInvalid bool CkSettings.DefaultThrowIfInvalid (false) Pass true to throw a CkUuidException that says why, instead of answering Guid.Empty, when at is not a date or lies before 1970, the epoch the id counts from.

Returns

When Default With throwIfInvalid: true
No moment, or a readable one A new RFC 9562 version 7 UUID The UUID
Rejected: at unreadable or out of range Guid.Empty Throws CkUuidException — carries Input, Expected and Reason

The moment sits in the first 48 bits and random bits follow, so ids made in sequence sort in sequence — what a database index wants, and what Guid.NewGuid()'s random version 4 does not give it. Pin at in tests and for back-dated records.

Guid id = CkUuid.NewV7();                          // now
Guid old = CkUuid.NewV7(at: "2026-08-31T14:05:00Z");   // sorts before id

Explain

Why not — in words, without an exception.

string Explain(
    object? input = null,
    bool treatZerosAsMissing = true
)
Parameter Type Default What it does
input object? null The value: text in any everyday shape, or a boxed Guid.
treatZerosAsMissing bool true Counts the all-zeros UUID as missing.

Returns

When You get
The value passes the reader ""
It does not The reason, the same words the exception would carry — an answer, not a failure; it never throws

The form-friendly twin of throwIfInvalid: the message to show beside the field, without a try and catch. Every class with a reader has one, on the reader's own rules, so the reason is exactly what the reader would say.

CkUuid.Explain("junk");                                     // -> "not a UUID in a known shape"
CkUuid.Explain("00000000-0000-0000-0000-000000000000");     // -> "the all-zeros UUID that means missing"

Good to know

  • ToGuid has no fallback parameter — on purpose. An identifier names one specific thing; an invented identity is worse than none. Rejection is always Guid.Empty, so you can catch it — never a made-up id that quietly corrupts deduplication.
  • All zeros means missing, by default. 00000000-0000-0000-0000-000000000000 is what databases and serializers emit when nobody set a value — the 1900-01-01 of identifiers. Every reader takes treatZerosAsMissing (default true) except Version, IsStandard and IsVersion, which always count zeros as missing; ToGuidOrNull turns that missing value into an honest null, and IsNil is the one method that answers true to it.
  • The validators answer false, never Guid.Empty. IsUuid, IsNil, IsCanonical, IsStandard, IsVersion, IsFromName and SameUuid answer false both for "no" and for "not a UUID"; pass throwIfInvalid: true when the difference matters. IsVersion never takes the flag.
  • IsCanonical judges the shape, Canonical reads any. IsCanonical("{…}") is false while Canonical("{…}") reads it fine. Use the validator where a field must already hold canonical text; use the reader everywhere else.
  • With the default on, Guid.Empty is an unambiguous signal. No valid read can produce it, so result == Guid.Empty reliably means "rejected". Turn treatZerosAsMissing off and that signal becomes ambiguous — prefer Canonical and its "" there.
  • Four shapes in, plus the urn:uuid: prefix. Bare digits, hyphenated, braced, parenthesized, any casing. The exotic hex-struct "X" form ({0x08d3f9c6,0x5e4a,...}) is source code, not data, and is rejected — in reading and as a Format shape.
  • FromName never cleans the name. " Claim-1 " and "claim-1" derive different UUIDs; normalise the name yourself, consistently, before deriving.
  • A boxed Guid reads directly. Values coming off a database reader as object go straight in — no .ToString() needed. CkDictionary uses the same reading for ToGuid on payload bags, and CkSentinel applies the same all-zeros verdict on the way to storage.
  • Non-empty in, empty out means rejected for Canonical and Format — the standard CommonKit signal (see How it works).

If you want errors instead

Pass throwIfInvalid: true and a value that cannot be used raises a CkUuidException (from SafeCoder.CommonKit.Exceptions) instead of returning the rejection value. The exception carries the Input, what was Expected and a short Reason, flattened into a one-line message.

CkUuid.ToGuid(
    input: "junk",
    throwIfInvalid: true
);   // throws CkUuidException — the message says why

ToGuidOrNull has no throwIfInvalid parameter and never throws — null is its answer for anything unusable. When a bad value should be an error, read it with ToGuid and the flag instead.