Troubleshooting
"Type must be partial"
error CS0260: Missing partial modifier on declaration of type 'Money'
Add partial to your type declaration:
// Wrong
[ValueObject]
public class Money { ... }
// Correct
[ValueObject]
public partial class Money { ... }
Generated code not appearing
- Ensure the
ZeroAlloc.ValueObjectsNuGet package is installed (not just referenced as a project without the correct metadata) - Rebuild the project (
Build → Rebuild Solutionordotnet build) - In Visual Studio, check Analyzers under the project's Dependencies node to confirm the generator is loaded
- Verify the type is
partialand the attribute namespace isZeroAlloc.ValueObjects
Equality not working as expected
If == returns false for two objects you expect to be equal, check:
1. Are the right properties included?
Use [EqualityMember] to be explicit:
[ValueObject]
public partial class Product
{
[EqualityMember] public string Sku { get; }
[EqualityMember] public string Name { get; }
// Other props excluded
}
2. Are properties normalized in the constructor?
If one value is "USD" and another is "usd", they are not equal. Normalize in the constructor:
public Money(decimal amount, string currency)
{
Amount = amount;
Currency = currency.ToUpperInvariant(); // normalize
}
3. Are nested reference-type properties using value equality?
If a property is itself a class without overridden equality, the generated comparison falls back to reference equality. Ensure nested types also use [ValueObject] or otherwise implement value equality.
[ValueObject]
public partial class Shipment
{
public Money Cost { get; } // Money also has [ValueObject] — uses its Equals()
public string Carrier { get; }
}
ToString output is not what I want
The generated ToString follows the record convention: TypeName { Prop1 = val1, Prop2 = val2 }. Override it in your partial declaration:
[ValueObject]
public partial class Money
{
public decimal Amount { get; }
public string Currency { get; }
// Overrides the generated version
public override string ToString() => $"{Amount:F2} {Currency}";
}
Struct is generated as a class (or vice versa)
Check the ForceClass property:
[ValueObject]on apartial struct→ generatesreadonly partial struct[ValueObject(ForceClass = true)]on apartial struct→ generatessealed partial class[ValueObject]on apartial class→ generatessealed partial class
Compiler warning: CS0659 or CS0661
These warnings appear when you override only one of Equals/GetHashCode or only operator ==/operator !=. They should not occur with the generator since it always emits the full set. If you see them, check that you haven't added a partial Equals or GetHashCode that conflicts with the generated one.