Table of Contents

Class RequiredInt<TSelf>

Namespace
Trellis
Assembly
Trellis.Primitives.dll

Base class for creating strongly-typed integer value objects that cannot have the default (zero) value. Provides a foundation for entity identifiers, counts, and other domain concepts represented by integers.

public abstract class RequiredInt<TSelf> : ScalarValueObject<TSelf, int>, IComparable<ValueObject>, IEquatable<ValueObject>, IConvertible where TSelf : RequiredInt<TSelf>, IScalarValue<TSelf, int>

Type Parameters

TSelf
Inheritance
RequiredInt<TSelf>
Implements
Inherited Members
Extension Methods

Examples

Creating a strongly-typed entity identifier:

// Define the value object (partial keyword enables source generation)
public partial class TicketNumber : RequiredInt<TicketNumber>
{
}

// The source generator automatically creates:
// - IScalarValue<TicketNumber, int> interface implementation
// - public static Result<TicketNumber> TryCreate(int value, string? fieldName = null)
// - public static Result<TicketNumber> TryCreate(int? value, string? fieldName = null)
// - public static Result<TicketNumber> TryCreate(string? value, string? fieldName = null)
// - public static TicketNumber Parse(string s, IFormatProvider? provider)
// - public static bool TryParse(string? s, IFormatProvider? provider, out TicketNumber result)
// - public static explicit operator TicketNumber(int value)
// - private TicketNumber(int value) : base(value) { }

// Usage examples:

// Create from existing integer with validation
var result1 = TicketNumber.TryCreate(12345);
// Returns: Success(TicketNumber) if value != 0
// Returns: Failure(ValidationError) if value == 0

// Create from string with validation
var result2 = TicketNumber.TryCreate("12345");
// Returns: Success(TicketNumber) if valid integer format
// Returns: Failure(ValidationError) if invalid format or zero

// With custom field name for validation errors
var result3 = TicketNumber.TryCreate(input, "ticket.number");
// Error field will be "ticket.number" instead of default "ticketNumber"

Multiple strongly-typed integer IDs in the same domain:

public partial class InvoiceNumber : RequiredInt<InvoiceNumber> { }
public partial class LineNumber : RequiredInt<LineNumber> { }

public class Invoice
{
    public InvoiceNumber Number { get; }
    private readonly List<InvoiceLine> _lines = [];

    // Compiler prevents mixing IDs:
    // AddLine(invoiceNumber); // Won't compile - type safety!
}

Remarks

This class extends ScalarValueObject<TSelf, T> to provide a specialized base for integer-based value objects with automatic validation that prevents zero/default integers. When used with the partial keyword, the PrimitiveValueObjectGenerator source generator automatically creates:

  • IScalarValue<TSelf, int> implementation for ASP.NET Core automatic validation
  • TryCreate(int) - Factory method for integers (required by IScalarValue)
  • TryCreate(int?, string?) - Factory method with zero validation and custom field name
  • TryCreate(string?, string?) - Factory method for parsing strings with validation
  • IParsable<T> implementation (Parse, TryParse)
  • JSON serialization support via ParsableJsonConverter<T>
  • Explicit cast operator from int
  • OpenTelemetry activity tracing

Common use cases:

  • Legacy entity identifiers (CustomerId, OrderId when using int IDs)
  • Reference numbers (InvoiceNumber, TicketNumber)
  • Sequence numbers requiring non-zero values
  • Any domain concept requiring a non-zero integer identifier

Benefits over plain integers:

  • Type safety: Cannot accidentally use CustomerId where OrderId is expected
  • Validation: Prevents zero/default integers at creation time
  • Domain clarity: Makes code more self-documenting and expressive
  • Serialization: Consistent JSON and database representation

Constructors

RequiredInt(int)

Initializes a new instance of the RequiredInt<TSelf> class with the specified integer value.

protected RequiredInt(int value)

Parameters

value int

The integer value. Must not be zero.

Remarks

This constructor is protected and should be called by derived classes. When using the source generator (with partial keyword), a private constructor is automatically generated that includes validation.

Direct instantiation should be avoided. Instead, use the generated factory methods:

  • TryCreate(int, string?) - Create from int with validation
  • TryCreate(int?, string?) - Create from nullable int with validation
  • TryCreate(string?, string?) - Create from string with validation

See Also