Exceções e desempenho
Nota
Este conteúdo é reimpresso com permissão da Pearson Education, Inc., a partir 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 revisto na terceira edição. Algumas das informações nesta página podem estar desatualizadas.
Uma preocupação comum relacionada às exceções é que, se as exceções forem usadas para código que falha rotineiramente, o desempenho da implementação será inaceitável. Trata-se de uma preocupação válida. Quando um membro lança uma exceção, seu desempenho pode ser ordens de magnitude mais lento. No entanto, é possível alcançar um bom desempenho respeitando estritamente as 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 Tester-Doer Pattern ou o Try-Parse Pattern, descritos nas próximas duas seções.
Padrão Tester-Doer
Às vezes, o desempenho de um membro que lança exceções pode ser melhorado dividindo o membro em dois. Vamos olhar para o AddICollection<T> método da interface.
ICollection<int> numbers = ...
numbers.Add(1);
O método Add
é lançado se a coleção for somente leitura. Isso pode ser um problema de desempenho em cenários em que se espera que a chamada de método falhe com frequência. Uma das maneiras de mitigar 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 no nosso exemplo é a propriedade IsReadOnly
, é referido como o testador. O membro usado para executar uma operação de lançamento potencial, o Add
método em nosso exemplo, é referido como o fazedor.
✔️ CONSIDERE o Tester-Doer Pattern para membros que podem lançar exceções em cenários comuns para evitar problemas de desempenho relacionados a exceções.
Padrão Try-Parse
Para APIs extremamente sensíveis ao desempenho, um padrão ainda mais rápido do que o Tester-Doer Pattern descrito na seção anterior deve ser usado. O padrão pede para ajustar o nome do membro para tornar um caso de teste bem definido uma parte da semântica do membro. Por exemplo, DateTime define um Parse método que lança uma exceção se a análise de uma cadeia de caracteres falhar. Ele também define um método correspondente TryParse que tenta analisar, mas retorna false se a análise não for bem-sucedida e retorna o resultado de uma análise bem-sucedida usando um out
parâmetro.
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 que não seja a tentativa bem definida, o membro ainda deve lançar uma exceção correspondente.
✔️ CONSIDERE o padrão Try-Parse para membros que podem lançar exceções em cenários comuns para evitar problemas de desempenho relacionados a exceções.
✔️ DO use o prefixo "Try" e o tipo de retorno booleano para métodos que implementam esse padrão.
✔️ DO fornece um membro que lança exceções para cada membro usando o padrão Try-Parse.
© Partes 2005, 2009 Microsoft Corporation. Todos os direitos reservados.
Reimpresso com permissão da Pearson Education, Inc., de Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, 2nd Edition por Krzysztof Cwalina e Brad Abrams, publicado em 22 de outubro de 2008 por Addison-Wesley Professional como parte da Microsoft Windows Development Series.