Skip to main content

ZeroAlloc.ValueObjects — Documentation

Zero-allocation, source-generated value object equality for existing .NET domain types.

Same performance as record — without forcing the record keyword on your domain model.


Contents​

PageDescription
Why this library?The problem with CFE, why not just use record
InstallationNuGet install, requirements
Getting StartedStep-by-step quickstart with core concepts
Attribute Reference[ValueObject], [ValueObjectFactory], [EqualityMember], [IgnoreEqualityMember]
Member SelectionHow properties are chosen for equality
What Gets GeneratedExact code the generator emits
Struct vs. ClassWhen to use each, ForceClass
Nullable PropertiesNull-safe comparison generation
Usage PatternsDictionary keys, HashSets, LINQ, EF Core, pattern matching
Migration GuideFrom CFE ValueObject, from manual equality
PerformanceBenchmark results and how to run them
Design & LimitationsTrade-offs, things not generated
TroubleshootingCommon errors and fixes
DiagnosticsZAVO001–ZAVO003 reference
TestingTesting value objects — equality, hash codes, serialization
Examples
E-CommerceProductId, Money, ShippingAddress, Discount
FinanceIban, CurrencyPair, AccountNumber
HR / IdentityEmailAddress, EmployeeId, FullName
GeospatialCoordinates, GeoRegion
SchedulingDateRange, TimeSlot

Typed Identifiers​

[TypedId] is the companion attribute for strongly-typed IDs — OrderId, UserId, MessageId. Built-in ULID / UUIDv7 / Snowflake / Sequential strategies, JSON, minimal API, and EF Core support out of the box.

PageDescription
Typed Identifiers overviewWhen to use [TypedId] vs [ValueObject], section contents
Getting startedInstall, declare, use — five-minute introduction
StrategiesULID, UUIDv7, Snowflake, Sequential — formats and trade-offs
Snowflake configurationWorker-ID setup via DI, env var, or factory, plus the ZeroAlloc.ValueObjects.Hosting overload
JSON serializationSystem.Text.Json integration, AOT safety
ASP.NET minimal API bindingRoute and query binding via IParsable<T>
EF Core integrationZeroAlloc.ValueObjects.EfCore conventions
DiagnosticsZATI001–ZATI010 reference
Production checklistOperational caveats and audit questions
InternalsGenerator pipeline and zero-allocation techniques

Quick Example​

using ZeroAlloc.ValueObjects;

[ValueObject]
public partial class Money
{
public decimal Amount { get; }
public string Currency { get; }

public Money(decimal amount, string currency)
{
Amount = amount;
Currency = currency;
}
}
var a = new Money(100m, "USD");
var b = new Money(100m, "USD");

a == b // true
a.GetHashCode() // same as b — safe as dict key
a.ToString() // "Money { Amount = 100, Currency = USD }"

Zero allocations. No record keyword. No base class required.