Exceções

Este guia trata apenas de User-Exceptions - System-Errors geralmente são fatais e nunca devem ser capturados.

Captura de exceções

Um caso comum de exceções é a validação de entradas do usuário potencialmente inválidas. Quando uma exceção for lançada, a pilha será deslocada até que o primeiro manipulador de exceção correspondente seja encontrado.

try
{
    readText("dummyFile");
}
catch (FileException e)
{
    // ...
}

É possível ter vários blocos catch e um bloco finally que é executado independentemente da ocorrência de um erro. As exceções são lançadas com throw.

try
{
    throw new StringException("You shall not pass.");
}
catch (FileException e)
{
    // ...
}
catch (StringException e)
{
    // ...
}
finally
{
    // ...
}

Lembre-se de que o scope guard geralmente é uma solução melhor para o padrão try-finally.

Exceções personalizadas

É possível herdar facilmente de Exception e criar exceções personalizadas:

class UserNotFoundException : Exception
{
    this(string msg, string file = __FILE__, size_t line = __LINE__) {
        super(msg, file, line);
    }
}
throw new UserNotFoundException("D-Man is on vacation");

Entre em um mundo seguro com o nothrow

O compilador D pode garantir que uma função não cause efeitos colaterais catastróficos. Essas funções podem ser anotadas com a palavra-chave nothrow. O compilador D proíbe estaticamente o lançamento de exceções em funções nothrow.

bool lessThan(int a, int b) nothrow
{
    writeln("unsafe world"); // output can throw exceptions, thus this is forbidden
    return a < b;
}

Observe que o compilador é capaz de inferir atributos para o código de modelo automaticamente.

std.exception

É importante evitar o assert e o que será introduzido em breve contract programming para a entrada do usuário, pois o assert e os contratos são removidos quando compilados no modo de lançamento. Por conveniência std.exception fornece enforce que pode ser usado como o assert, mas lança Exceptions em vez de um AssertError.

import std.exception : enforce;
float magic = 1_000_000_000;
enforce(magic + 42 - magic == 42, "Floating-point math is fun");

// throw custom exceptions
enforce!StringException('a' != 'A', "Case-sensitive algorithm");

No entanto, há mais em std.exception. Por exemplo, quando o erro pode não ser fatal, é possível optar por collect:

import std.exception : collectException;
auto e = collectException(aDangerousOperation());
if (e)
    writeln("The dangerous operation failed with ", e);

Para verificar se uma exceção foi lançada nos testes, use assertThrown.

Maiores detalhes

rdmd playground.d