Validating objects at creation time

If we have more complex validation logic, we could introduce a factory method and a Result object to handle the validations better:

public record Result<T>
    public bool IsSuccess { get; private init; }
    public T? Value { get; private init; }
    public string? ErrorMessage { get; private init; }

    private Result(){}

    public static Result<T> Success(T value) => new() 
       IsSuccess = true, Value = value
    public static Result<T> Failure(string errorMessage) => new()
        IsSuccess = false, ErrorMessage = errorMessage

Here we declare the generic Result record, so now let’s see how to create the factory method for the Money value object:

public record Money
    private static readonly IReadOnlyCollection<string> SupportedCurrencies = new[]{"USD", "EUR"};

    public decimal Amount { get; }
    public string Currency { get; }
    private Money(decimal amount, string currency)
        Amount = amount;
        Currency = currency;

    public static Result<Money> Create(decimal amount, string currency)
            return Result<Money>.Failure($"{nameof(currency)} cannot be null or whitespace.");

            return Result<Money>.Failure($"'{currency}' is not supported.");
        return Result<Money>.Success(new(amount, currency));

Instead of throwing exceptions (or simply returning False), we return a Failure result (with a specific message), allowing the caller to handle this in a cleaner fashion.


Leave a Reply

Your email address will not be published. Required fields are marked *