Exceções no construtor e blocos using


Se uma determinada classe que está sendo criada possuir referências para outros objetos que são custosos, a boa prática é implementar o padrão Disposable, que nos permite explicitamente descartar estes recursos quando não mais precisamos deles. O padrão Disposable consiste na implementação de uma interface chamada IDisposable, que fornece um método Dispose, que dentro dele você fará toda a limpeza necessária.

Disparar exceções em construtores é algo comum, e que na maioria das vezes representam validações dos parâmetros que são passados à instância da classe que está sendo criada. Um cuidado especial nestes casos, é garantir que você nunca armazene nenhum objeto antes de tais validações, por exemplo:

public class MinhaClasse : IDisposable
{
    private IntPtr _ponteiro;
    private string _valor;

    public MinhaClasse(string valor, IntPtr ponteiro)
    {
        this._ponteiro = ponteiro;

        if (string.IsNullOrEmpty(valor))
            throw new ArgumentNullException(“valor”);

        this._valor = valor;
    }

    public void Dispose()
    {
        if (this._ponteiro != IntPtr.Zero)
            this._ponteiro = IntPtr.Zero;
    }

    ~MinhaClasse() { Dispose(); }
}

Ao criar a instância desta classe e definir o parâmetro valor como nulo, repare que antes da validação acontecer, o membro _ponteiro já estará com o valor armazenado. Mesmo que você esteja trabalhando da forma politicamente correta, que é implementando a interface IDisposable para a liberação dos recursos, você tem ainda outros problemas, já que ela não funciona por si só. Sabemos que a implementação desta interface é apenas uma convenção, mas para que a limpeza realmente funcione, o desenvolvedor deverá explicitamente invocar o método Dispose.

Neste caso, envolver a instância em um bloco using (que garante a chamada implícita do Dispose) não resolverá. Como sabemos, o using é açúcar sintático, pois na verdade ele é compilado para blocos try/finally. Se instanciarmos a classe dentro do using, a criação da instância será colocada fora do bloco try, e como a exceção está sendo disparada no construtor, o Dispose não será invocado e, infelizmente, teremos que esperar até o destrutor ser invocado, isso se o tivermos implementado.

Anúncios

2 comentários sobre “Exceções no construtor e blocos using

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s