Error Handling

17.1 Exceptions

class ValidationException : Exception
{
    this(string msg, string file = __FILE__, size_t line = __LINE__)
    {
        super(msg, file, line);
    }
}

void validate(int age)
{
    if (age < 0) throw new ValidationException("age must be non-negative");
}

void main()
{
    try
    {
        validate(-1);
    }
    catch (ValidationException e)
    {
        writeln("Invalid: ", e.msg, " at ", e.file, ":", e.line);
    }
    catch (Exception e)
    {
        writeln("Other: ", e.msg);
    }
    finally
    {
        writeln("cleanup");
    }
}

17.2 Throwable Hierarchy

Don't catch Errors in normal code. The program state is undefined afterwards. nothrow functions may still throw Errors.

Throwable
├── Exception      (recoverable: ConvException, FileException, ErrnoException, ...)
└── Error          (unrecoverable bugs: AssertError, RangeError, OutOfMemoryError, InvalidMemoryOperationError)

17.3 Helper Functions

import std.exception;
enforce(x > 0, "x must be positive");            // throws Exception if false
auto f = enforce(fopen(...), "cannot open");     // returns the value if it's truthy
enforce!FileException(exists(path), "missing");
auto e = collectException(riskyOp());            // returns the exception (or null)
assertThrown!ConvException("abc".to!int);        // in unittests
assertNotThrown(safeOp());
auto r = ifThrown("abc".to!int, 0);              // default on exception

17.4 assert and static assert

assert(x > 0, "x must be positive");     // removed in -release builds (except assert(0))
assert(0);                               // always halts: marks unreachable code
static assert(int.sizeof == 4, "unexpected int size");   // compile-time check

17.5 Scope Guards

Scope guards run in reverse order. They're cleaner than nested try/finally.

void transfer()
{
    lock();
    scope(exit) unlock();                    // always runs at scope exit
    beginTransaction();
    scope(failure) rollback();               // only if an exception propagates
    scope(success) commit();                 // only on normal exit
    doWork();
}

17.6 Error Handling Alternatives

Nullable!T / sentinel values, std.typecons.Expected-style libraries (e.g., expected on DUB), return codes in @nogc nothrow / BetterC code.