Reyrb.Guid.Namespace
10.0.0
dotnet add package Reyrb.Guid.Namespace --version 10.0.0
NuGet\Install-Package Reyrb.Guid.Namespace -Version 10.0.0
<PackageReference Include="Reyrb.Guid.Namespace" Version="10.0.0" />
<PackageVersion Include="Reyrb.Guid.Namespace" Version="10.0.0" />
<PackageReference Include="Reyrb.Guid.Namespace" />
paket add Reyrb.Guid.Namespace --version 10.0.0
#r "nuget: Reyrb.Guid.Namespace, 10.0.0"
#:package Reyrb.Guid.Namespace@10.0.0
#addin nuget:?package=Reyrb.Guid.Namespace&version=10.0.0
#tool nuget:?package=Reyrb.Guid.Namespace&version=10.0.0
GUID categories and namespaces
Both packages target .NET 10. Reyrb.Guid creates categorised random, named and
sequential IDs. Reyrb.Guid.Namespace adds declared namespaces and a source generator.
Categories
using Reyrb.Guid;
enum Category { None = -1, User = 0, Order = 1 }
var random = GuidCreator.CreateRandom(Category.User);
var sequential = GuidCreator.CreateSequential(Category.Order);
var named = GuidCreator.CreateNamed(namespaceId, "order-123", Category.Order);
if (GuidCategoryHelper.TryGetCategory<Category>(named, out var category, out var originalVersion))
{
// category == Category.Order; originalVersion == 5; named.Version == 13
}
Values 0 through 15 are categories. Any negative enum value leaves the source UUID
unchanged. Other values throw ArgumentOutOfRangeException, including large values
of enums backed by long or ulong. All eight enum underlying types are supported.
Decoding returns the numeric enum value even if it has no declared enum member.
The overload without originalVersion reads just the category. The original version
identifies the source algorithm; it does not recover the original GUID's overwritten bits.
Categorised GUIDs use a private format with reserved UUID version values:
12 for random v4, 13 for named v5, and 15 for sequential v7. These values work with
.NET Guid parsing and JSON serialization. PostgreSQL's uuid type accepts values
regardless of version.
They are not standardized UUID versions: strict validators can reject them, and a
future standard could assign these version numbers a different meaning. Version-aware
tools will not automatically interpret their original generation algorithm.
Names are case-sensitive and leading/trailing whitespace is preserved by both APIs.
UUIDNext normalizes names to Unicode NFC before hashing, so canonically equivalent
spellings such as é and e followed by a combining acute accent produce the same
ID. Empty names are supported; null names throw ArgumentNullException. Apply any
additional normalization, such as trimming or case folding, explicitly before calling.
Sequential IDs preserve UUIDNext's timestamp and twelve-bit counter. Successive
calls with nonnegative categories are strictly increasing under Guid.CompareTo
and ordinal comparison of canonical GUID strings, even when the category changes.
The category conversion cannot merge distinct timestamp/counter pairs allocated
by the shared UUIDNext generator, including concurrent calls. This describes
allocation order; it does not order concurrent call completion. Separate generator
instances and process restarts still rely on randomness for collision resistance,
so there is no absolute guarantee across them. SQL Server's uniqueidentifier
uses a different ordering. Do not mix uncategorised v7 and categorised version-15
IDs if you need strict ordering within the same millisecond.
Declared namespaces
Install the Reyrb.Guid.Namespace NuGet package; its generator is included as an
analyzer. A namespace consists of a non-abstract partial class without a base class,
containing only static readonly fields of namespace types:
using Reyrb.Guid;
internal partial class OrderNamespaces : GuidNamespace
{
// Literal UUID seeds are independent of symbol names.
public static readonly OrderNamespaces Imported =
new("550e8400-e29b-41d4-a716-446655440000");
// Stable keys also survive namespace, class and field renames.
[GuidNamespaceKey("example.orders/v1")]
public static readonly OrderNamespaces Orders;
}
// In a method:
var plain = OrderNamespaces.Orders.NewNamedGuid("order-123"); // UUIDv5
var tagged = OrderNamespaces.Orders.CreateNamespaced("order-123", Category.Order);
var seed = OrderNamespaces.Orders.NamespaceId;
The generated NamespaceId property exposes the seed for interoperability or for
pinning it as a literal UUID. Namespaces with equal seeds and equivalent NFC names produce
equal IDs, even when declared in different classes. Namespace object equality also
requires the same constructed namespace class.
Fields may be split across partial declarations. Internal, generic, nested and global-namespace classes are supported. Every containing type must also be partial. Interface aliases and escaped identifiers are supported. Generic constructions share the declared seed: type arguments are not part of the namespace key.
A field without an initializer or GuidNamespaceKey derives its seed from its fully
qualified C# type and field name. The generator reports GUID004 because renaming
that symbol changes every derived ID. Prefer a fixed seed or stable key; suppress
GUID004 explicitly if name-dependent identity is intentional. Keys must be nonempty
and cannot be combined with initializers. Reusing a key intentionally reuses a seed.
The generator reports invalid constant GUID strings in both new("...") and
new NamespaceType("...") forms, including constant expressions. Dynamic string
expressions are parsed at initialization and can still fail at runtime.
Project references do not propagate analyzers. When consuming the namespace project from this repository, also reference the generator as shown in the example project:
<ProjectReference Include="../Reyrb.Guid.Namespace/Reyrb.Guid.Namespace.csproj" />
<ProjectReference Include="../Reyrb.Guid.Namespace.Generator/Reyrb.Guid.Namespace.Generator.csproj"
OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
Category layout
All offsets below refer to network/big-endian byte order:
| Bits / bytes | Contents |
|---|---|
| High bit of byte 6 | Category flag; sets source versions 4, 5, 7 to 12, 13, 15 |
| High two bits of byte 8 | RFC variant 10 |
Bits 5..4 of byte 15 (mask 0x30) |
High two category bits |
Bits 1..0 of byte 15 (mask 0x03) |
Low two category bits |
The final two hexadecimal digits each have the bit layout RRCC: two retained
source bits followed by two category bits. Each digit can therefore take four
different values for a given category. All other source payload bits are preserved.
The four category bits leave 118 random bits for random IDs, 118 hash bits for
named IDs, and 58 random bits in addition to the 48-bit timestamp and 12-bit counter
for sequential IDs. Encoding the original creation version uses only the existing
version field and consumes no random bits.
The decoder accepts only version values 12, 13 and 15 with the RFC variant and returns the original version by clearing the high version bit. Other values return false with zeroed outputs. It assumes those reserved version values belong to this format; it cannot distinguish unrelated uses of them. The standard reserves versions 9 through 15 for future definitions.
This placement preserves UUIDNext's sequential counter, but other GUID generators can use the trailing bits differently. It is not a guarantee that arbitrary externally generated GUIDs can be categorised without affecting their uniqueness.
Namespace seed layout
Stable namespace seeds use the first 16 SHA-256 bytes of the UTF-8 string
Reyrb.Guid.Namespace/v1: followed by the exact key. The version and variant bits
are replaced with UUIDv8 and the RFC variant. The result is interpreted in network
byte order. For example, reyrb.tests.shared produces
a81c36a3-7d91-8b47-8bfb-ab987eba94fa.
Verification
dotnet build Reyrb.sln --configuration Release
dotnet test Reyrb.Guid.Tests/Reyrb.Guid.Tests.csproj --configuration Release --no-build
bash eng/test-guid-packages.sh
The namespace project declares its generator build dependency and packages the resolved DLL, including when building from a clean checkout or using a custom artifacts directory.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Reyrb.Guid (>= 10.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|