Phase 6 of 30 · Topic 6.5

Null Object Pattern & Functional `Option<T>` / `Result<T>` Types

1Concept

The Null Object Pattern replaces null returns with neutral do-nothing objects. Functional `Option<T>` (Some vs None) and `Result<T>` make absence or failure an explicit return type in domain modeling.

2Architecture Diagram

Service Query
       │
  Found?
    ├── YES ──> Result.Success(User)
    └── NO  ──> Result.Failure("User not found in partition")

3Code Example

C# 13 & .NET 9
using System;

public readonly record struct Result<T>
{
    public bool IsSuccess { get; }
    public T Value { get; }
    public string Error { get; }

    private Result(T value) { IsSuccess = true; Value = value; Error = string.Empty; }
    private Result(string error) { IsSuccess = false; Value = default!; Error = error; }

    public static Result<T> Success(T value) => new(value);
    public static Result<T> Failure(string error) => new(error);
}

public class ResultPatternDemo
{
    public static Result<string> FetchApiKey(int tenantId)
    {
        if (tenantId == 100) return Result<string>.Success("SEC-KEY-998877");
        return Result<string>.Failure("Tenant not provisioned.");
    }

    public static void Main()
    {
        var res = FetchApiKey(100);
        if (res.IsSuccess)
        {
            Console.WriteLine($"API Key: {res.Value}");
        }
        else
        {
            Console.WriteLine($"Error: {res.Error}");
        }
    }
}

4Expected Output

API Key: SEC-KEY-998877

5Key Takeaways

  • The `Result<T>` pattern avoids costly exception throwing for normal business validation flows.
  • Struct-based `Result<T>` creates zero GC heap allocation overhead.
  • Cleanly interoperates with C# 13 pattern matching.