Compartilhar via


Exceções e desempenho

Observação

Este conteúdo é reimpresso com permissão da Pearson Education, Inc. de Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, 2nd Edition. Essa edição foi publicada em 2008 e, desde então, o livro foi totalmente revisado na terceira edição. Algumas das informações nesta página podem estar desatualizadas.

Uma preocupação comum relacionada a exceções é que, se exceções forem usadas para código que falha rotineiramente, o desempenho da implementação será inaceitável. A preocupação é válida. Quando um membro lança uma exceção, seu desempenho pode ser ordens de magnitude mais lentas. No entanto, é possível obter um bom desempenho, aderindo estritamente às diretrizes de exceção que não permitem o uso de códigos de erro. Dois padrões descritos nesta seção sugerem maneiras de fazer isso.

❌ NÃO use códigos de erro devido a preocupações de que exceções possam afetar negativamente o desempenho.

Para melhorar o desempenho, é possível usar o padrão Testador-Executor ou o padrão Tentar-Analisar, descrito nas próximas duas seções.

Padrão Testador-Executor

Às vezes, o desempenho de um membro gerador de exceções pode ser aprimorado ao dividir o membro em dois. Vamos examinar o método Add da interface ICollection<T>.

ICollection<int> numbers = ...
numbers.Add(1);

O método Add gera exceção se a coleção for somente leitura. Isso pode ser um problema de desempenho em cenários nos quais se espera que a chamada de método falhe com frequência. Uma das maneiras de atenuar o problema é testar se a coleção é gravável antes de tentar adicionar um valor.

ICollection<int> numbers = ...
...
if (!numbers.IsReadOnly)
{
    numbers.Add(1);
}

O membro usado para testar uma condição, que em nosso exemplo é a propriedade IsReadOnly, é conhecido como o testador. O membro usado para executar uma operação potencialmente geradora de exceção, o método Add em nosso exemplo, é chamado de executor.

✔️ CONSIDERE o padrão Testador-Executor para membros que podem gerar exceções em cenários comuns para evitar problemas de desempenho relacionados a exceções.

Padrão Tentar-Analisar

Para APIs extremamente sensíveis ao desempenho, um padrão ainda mais rápido do que o padrão Testador-Executor descrito na seção anterior deve ser usado. O padrão exige o ajuste do nome do membro para tornar um caso de teste bem definido uma parte da semântica do membro. Por exemplo, DateTime define um método Parse que gera uma exceção se a análise de uma cadeia de caracteres falhar. Ele também define um método TryParse que tenta analisar, mas retorna false se a análise não for bem-sucedida e retornar o resultado de uma análise bem-sucedida usando um parâmetro out.

public struct DateTime
{
    public static DateTime Parse(string dateTime)
    {
        ...
    }
    public static bool TryParse(string dateTime, out DateTime result)
    {
        ...
    }
}

Ao usar esse padrão, é importante definir a funcionalidade try em termos estritos. Se o membro falhar por qualquer motivo diferente da tentativa bem definida, o membro ainda deverá gerar uma exceção correspondente.

✔️ CONSIDERE o padrão Tentar-Analisar para membros que podem gerar exceções em cenários comuns para evitar problemas de desempenho relacionados a exceções.

✔️ USE o prefixo "Try" e o tipo de retorno booliano para métodos que implementam esse padrão.

✔️ FORNEÇA um membro que gera exceções para cada membro usando o padrão Tentar-Analisar.

Portions © 2005, 2009 Microsoft Corporation. Todos os direitos reservados.

Reimpresso com permissão da Pearson Education, Inc. das Diretrizes de Design do Framework: convenções, linguagens e padrões para bibliotecas do .NET reutilizável, 2ª edição por Krzysztof Cwalina e Brad Abrams, publicado em 22 de outubro de 2008 por Addison-Wesley Professional como parte da série de desenvolvimento do Microsoft Windows.

Confira também