Práticas recomendadas para tratamento de exceções

Um conjunto bem-estruturado de blocos de código de manipulação de erros pode tornar um programa mais robusto e menos propenso a falhas porque o aplicativo lida com esses erros.A lista a seguir contém sugestões sobre as práticas recomendadas para tratamento de exceções:

  • Saiba quando configurar um bloco try/catch.Por exemplo, você pode verificar programaticamente uma condição que é provável de ocorrer sem usar tratamento de exceções.Em outras situações, usar tratamento de exceções para capturar uma condição de erro é apropriado.

    O exemplo a seguir usa uma instrução if para verificar se uma conexão é fechada.Você pode usar esse método em vez de lançar uma exceção se a conexão não for fechada.

       If conn.State <> ConnectionState.Closed Then
          conn.Close()
       End If
    
       if(conn.State != ConnectionState.Closed)
          conn.Close();
    

    No exemplo a seguir, uma exceção é lançada se a conexão não for fechada.

       Try
          conn.Close()
       Catch ex As InvalidOperationException
          'Do something with the error or ignore it.
       End Try
    
       try {
         conn.Close();
       }
       catch(InvalidOperationException ex) {
         //Do something with the error or ignore it.
       }
    

    O método escolhido depende da frequência com que você espera que o evento ocorra.Se o evento for realmente excepcional e for um erro (como um final de arquivo inesperado), usar tratamento de exceções é melhor porque menos código é executado no caso normal.Se o evento ocorre com frequência, usar o método programático para verificar erros é melhor.Nesse caso, se ocorrer uma exceção, a exceção levará mais tempo para ser tratada.

  • Use blocos try/finally ao redor de códigos que potencialmente podem gerar uma exceção e centralize suas instruções catch em um local.Dessa forma, a instrução try gera a exceção, a instrução finally fecha ou desaloca recursos, e a instrução catch lida com a exceção a partir de um local central.

  • Sempre ordene exceções em blocos catch da mais específica para a menos específica.Essa técnica lida com a exceção específica antes que ela seja passada para um bloco catch mais geral.

  • Termine nomes de classes de exceção com a palavra "Exceção".Por exemplo:

    Public Class EmployeeListNotFoundException
        Inherits Exception
    
    public class MyFileNotFoundException : Exception {
    }
    
  • Ao criar exceções definidas pelo usuário, você deve garantir que os metadados para as exceções estejam disponíveis para códigos executando remotamente, inclusive quando exceções ocorrem entre domínios de aplicativo.Por exemplo, suponha que domínio de aplicativo A cria o domínio de aplicativo B, que executa o código que lança uma exceção.domínio do aplicativo para detectar e tratar a exceção corretamente, ele deve ser capaz de localizar o assembly que contém a exceção lançada pelo aplicativo domínio B.Se domínio do aplicativo B lança uma exceção que está contida em um assembly em sua base de aplicativo, mas não em domínio do aplicativo do aplicativo base, um domínio do aplicativo será não conseguir encontrar a exceção e o common linguagem tempo de execução lança um FileNotFoundException. Para evitar essa situação, você pode implantar o assembly que contém as informações de exceção de duas maneiras:

    • Coloque o assembly em uma base de aplicativo comum compartilhada por ambos os domínios de aplicativo

      - ou -

    • Se os domínios não compartilham uma base de aplicativos comum, assine o assembly que contém as informações de exceção com um nome forte e implante o assembly no cache global de assemblies.

  • Em C# e C++, use pelo menos os três construtores comuns ao criar suas próprias classes de exceção.Para um exemplo, consulte Como: Criar exceções definida pelo usuário.

  • Na maioria dos casos, use os tipos de exceção pré-definidos.Defina novos tipos de exceção somente para cenários programáticos.Apresente uma nova classe de exceção para permitir que um programador realize uma ação diferente em códigos com base na classe de exceção.

  • Para a maioria dos aplicativos, derive exceções personalizadas da classe Exception.Pensou-se originalmente que exceções personalizadas deveriam derivar da classe ApplicationException; no entanto, na prática isso não acresccentou valor significativo.

  • Inclua uma sequência de caracteres de descrição localizada em cada exceção.Quando o usuário vê uma mensagem de erro, ela é derivada da sequência de caracteres de descrição da exceção que foi lançada, em vez da classe de exceção.

  • Use mensagens de erro gramaticalmente corretas, incluindo a pontuação final.Cada sentença em uma sequência de caracteres descrição de uma exceção deve terminar com um ponto final.

  • Forneça propriedades Exception para acesso programático.Inclua informações extras em uma exceção (além da sequência de caracteres de descrição) somente quando há um cenário programático onde as informações adicionais são úteis.

  • Retorne null para casos extremamente comuns de erro.Por exemplo, Open retorna null se o arquivo não for encontrado, mas lança uma exceção se o arquivo estiver bloqueado.

  • Crie classes de modo que uma exceção nunca seja apresentada no uso normal.Por exemplo, uma FileStream classe expõe uma outra maneira de determinar se o fim do arquivo foi alcançado.Isso evita a exceção que é lançada se você ler depois do final do arquivo.O exemplo a seguir mostra como ler até o final do arquivo.

    Class FileRead
    
        Public Sub Open(ByVal fileToRead As FileStream)
    
            ' This If statement is optional
            ' as it is very unlikely that
            ' the stream would ever be null
            If IsDBNull(fileToRead) Then
                Throw New System.ArgumentNullException()
            End If
    
            Dim b As Integer
    
            ' Set the stream position to the beginning of the file.
            fileToRead.Seek(0, SeekOrigin.Begin)
    
            ' Read each byte to the end of the file.
            For i As Integer = 0 To fileToRead.Length
                b = fileToRead.ReadByte()
                Console.Write(b.ToString())
                ' Or do something else with the byte.
            Next
        End Sub
    
    End Class
    class FileRead {
        public void Open(FileStream fileToRead) 
        {
    
            // This if statement is optional
            // as it is very unlikely that
            // the stream would ever be null.
            if (fileToRead == null)
            {
                throw new System.ArgumentNullException();
            }
    
            int b;
    
            // Set the stream position to the beginning of the file.
            fileToRead.Seek(0, SeekOrigin.Begin);
    
            // Read each byte to the end of the file.
            for (int i = 0; i < fileToRead.Length; i++)
            {
                b = fileToRead.ReadByte();
                Console.Write(b.ToString());
                // Or do something else with the byte.
            }
        }
    } 
    
  • Lançe um InvalidOperationException se uma propriedade de definição ou chamada de método não for adequada dado o estado atual do objeto.

  • Lançe um ArgumentException ou uma classe derivada de ArgumentException se forem passados parâmetros inválidos.

  • O rastreamento de pilha começa na instrução na qual a exceção é lançada e termina na instrução catch que captura a exceção.Esteja ciente desse fato quando decidir onde colocar uma instrução throw.

  • Use métodos de construtor de exceção.É comum uma classe lançar a mesma exceção a partir de locais diferentes em sua implementação.Para evitar código excessivo, use métodos auxiliares que criam a exceção e a retornam.Por exemplo:

    Class File
       Private fileName As String
    
       Public Function Read(bytes As Integer) As Byte()
          If Not ReadFile(handle, bytes) Then
             Throw NewFileIOException()
          End If
       End Function 'Read
    
       Function NewFileIOException() As FileException
          Dim description As String = __unknown ' Build localized string, including fileName.
          Return New FileException(description) '
       End Function 'NewFileIOException
    End Class 'File
    
    class File {
        string fileName;
        public byte[] Read(int bytes) {
            if (!ReadFile(handle, bytes))
                throw NewFileIOException();
        }
        FileException NewFileIOException() {
            string description = // Build localized string, including fileName.
            return new FileException(description);
         }
    }
    

    Como alternativa, use a exceção do construtor para criar a exceção.Isso é mais apropriado para classes de exceção globais, como ArgumentException.

  • Lançe exceções em vez de retornar um código de erro ou HRESULT.

  • Limpe resultados intermediários ao lançar uma exceção.Os chamadores devem ser capazes de pressupor que não haja efeitos colaterais quando uma exceção for lançada a partir de um método.

Consulte também

Outros recursos

Tratamento e lançamento de exceções