Outras dicas

Eles são uma má idéia em geral , porque é uma condição verdadeiramente raro em que uma falha (condições excepcionais, mais genericamente) está devidamente atendidas sem resposta qualquer. Além disso, os blocos catch vazios são uma ferramenta comum usada por pessoas que usam o mecanismo de exceção para a verificação de erros que eles deveriam estar fazendo preventivamente.

Para dizer que é sempre ruim não é verdade ... isso é verdade para muito pouco. Pode haver circunstâncias em que ou você não se importa que houve um erro ou que a presença do erro de alguma forma indica que você não pode fazer nada sobre isso de qualquer maneira (por exemplo, ao escrever um erro anterior para um arquivo de log de texto e você receber um IOException, o que significa que você não poderia escrever o novo erro de qualquer maneira).

Eu não coisas se estendem até a dizer que quem usa blocos catch vazio é um programador ruim e não sabe o que está fazendo ...

Eu uso blocos catch vazio, se necessário. Às vezes, programador de biblioteca Eu estou consumindo não sabe o que está fazendo e joga exceções, mesmo em situações em que ninguém precisa.

Por exemplo, considere alguma biblioteca servidor http, eu não poderia me importar menos se o servidor lança exceção porque o cliente tem desconectado e index.html não pôde ser enviada.

Há casos raros em que podem ser justificadas. Em Python muitas vezes você vê este tipo de construção:

try:
    result = foo()
except ValueError:
    result = None

Assim, pode ser OK (dependendo do aplicativo) para fazer:

result = bar()
if result == None:
    try:
        result = foo()
    except ValueError:
        pass # Python pass is equivalent to { } in curly-brace languages
 # Now result == None if bar() returned None *and* foo() failed

Em um recente projeto .NET, eu tinha que escrever código para enumerar plugin de DLLs para encontrar classes que implementam uma determinada interface. O pouco relevante do código (em VB.NET, sorry) é:

    For Each dllFile As String In dllFiles
        Try
            ' Try to load the DLL as a .NET Assembly
            Dim dll As Assembly = Assembly.LoadFile(dllFile)
            ' Loop through the classes in the DLL
            For Each cls As Type In dll.GetExportedTypes()
                ' Does this class implement the interface?
                If interfaceType.IsAssignableFrom(cls) Then

                    ' ... more code here ...

                End If
            Next
        Catch ex As Exception
            ' Unable to load the Assembly or enumerate types -- just ignore
        End Try
    Next

Embora, mesmo neste caso, eu admito que registrando a algum lugar falha provavelmente seria uma melhoria.

blocos catch vazio são geralmente colocados em porque o codificador não sabe realmente o que estão fazendo. Na minha organização, um bloco catch vazio deve incluir um comentário a respeito de porque não fazer nada com a exceção é uma boa idéia.

Em uma nota relacionada, a maioria das pessoas não sabem que um bloco try {} pode ser seguido com qualquer um catch {} ou um finally {}, apenas uma é necessária.

As excepções só deve ser acionada se não há verdadeiramente uma exceção - algo acontecendo além da norma. Um bloco catch vazio basicamente diz "alguma coisa ruim está acontecendo, mas eu simplesmente não se importam". Esta é uma má idéia.

Se você não quer tratar a exceção, deixá-lo propagar para cima até que ele atinja um código que pode lidar com isso. Se nada pode tratar a exceção, ele deve tomar a baixo aplicação.

Eu acho que está tudo bem se você pegar um particular, tipo de exceção de que você sabe que só vai ser levantada por um particular, razão, e espera que essa exceção e realmente não precisa fazer nada sobre isso.

Mas, mesmo nesse caso, uma mensagem de depuração pode estar em ordem.

Por Josh Bloch - Item 65: Não ignore exceções de Effective Java :

  1. Um bloco catch vazio derrota o propósito de exceções
  2. No mínimo, o bloco catch deve conter um comentário explicando por que é apropriado para ignorar a exceção.

Um bloco catch vazio é essencialmente dizendo: "Eu não quero saber o que os erros são jogados, eu só vou ignorá-los."

É semelhante a On Error Resume Next do VB6, exceto que qualquer coisa no bloco try após a exceção é lançada será ignorado.

O que não ajuda quando alguma coisa, então pausas.

Isto vai de mãos dadas com "Não use exceções para o fluxo do programa de controle.", E, "Só use exceções para circunstâncias excepcionais." Se estes são feitos, então exceções deve ser apenas ocorre quando há um problema. E se há um problema, você não quer falhar silenciosamente. Nos raros anomalias onde não é necessário para lidar com o problema que você deve pelo menos registrar a exceção, apenas no caso da anomalia torna-se não uma anomalia. A única coisa pior do que não está falhando silenciosamente.

Eu acho que um bloco catch completamente vazio é uma má idéia, porque não há maneira de inferir que ignorar a exceção foi o comportamento pretendido do código. Não é necessariamente ruim de engolir uma falsa exceção e devolução ou nulo ou algum outro valor, em alguns casos. O .NET Framework tem muitas "tentar" métodos que se comportam desta maneira. Como regra geral, se você engolir uma exceção, adicionar um comentário e uma declaração de registro se o registro de suportes de aplicação.

Porque se uma exceção é jogado você nunca vai vê-lo - não silenciosamente é a pior opção possível - você terá um comportamento errôneo e nenhuma idéia de olhar para onde isso está acontecendo. Pelo menos colocar uma mensagem log lá! Mesmo que seja algo que nunca pode acontecer '!

blocos catch vazio são uma indicação de um programador sem saber o que fazer com uma exceção. Eles estão suprimindo a exceção de possivelmente borbulhando e sendo tratados corretamente por um outro bloco try. Sempre tentar e fazer alguma coisa com a exceção você está pegando.

I encontrar o mais chato com instruções catch vazio é quando algum outro programador fez isso. O que quero dizer é quando você precisa para depurar o código de outra pessoa qualquer declaração catch vazio faz tal empreendimento mais difícil, então ele precisa ser. IMHO declarações de capturas deve sempre mostrar algum tipo de mensagem de erro - (. Alt em apenas em modo de depuração), mesmo que o erro não é tratado deve, pelo menos, detectá-lo

Nunca é provavelmente a coisa certa, porque você está passando silenciosamente todas possível exceção. Se há uma exceção específica que você está esperando, então você deve testar para isso, rethrow se não é sua exceção.

try
{
    // Do some processing.
}
catch (FileNotFound fnf)
{
    HandleFileNotFound(fnf);
}
catch (Exception e)
{
    if (!IsGenericButExpected(e))
        throw;
}

public bool IsGenericButExpected(Exception exception)
{
    var expected = false;
    if (exception.Message == "some expected message")
    {
        // Handle gracefully ... ie. log or something.
        expected = true;
    }

    return expected;
}

Geralmente, você só deve capturar as exceções que você pode realmente manipular. Isso significa ser o mais específico possível ao capturar exceções. Captura todas as exceções raramente é uma boa idéia e ignorando todas as exceções é quase sempre uma idéia muito ruim.

Eu só posso pensar em alguns casos em que um bloco catch vazio tem algum propósito significativo. Se o que quer exceção específica, você está pegando é "manipulado" por apenas tentar novamente a ação, não haveria necessidade de fazer qualquer coisa no bloco catch. No entanto, ainda seria uma boa idéia para registrar o fato de que a exceção ocorreu.

Outro exemplo: CLR 2.0 mudou a forma como exceções não tratadas no segmento finalizador são tratados. Antes de 2.0, o processo foi permitido sobreviver neste cenário. No CLR atual do processo é encerrado no caso de uma exceção não tratada no segmento finalizador.

Tenha em mente que você só deve implementar um finalizador se você realmente precisa de um e mesmo assim você deve fazer uma pequena quanto possível no finalizador. Mas se tudo o que trabalhar o seu finalizador deve fazer poderia lançar uma exceção, você precisa escolher entre o menor de dois males. Você quer encerrar a aplicação devido à exceção não tratada? Ou você deseja prosseguir em um estado mais ou menos indefinido? Pelo menos em teoria, o último pode ser o menor de dois males em alguns casos. Em aqueles casos o bloco de captura vazio iria impedir o processo de ser terminada.

eu quero dizer, por exemplo, às vezes você deseja obter alguma informação adicional de algum lugar (webservice, banco de dados) e você realmente não me importo se você vai obter esta informação ou não. Então você tentar obtê-lo, e se acontecer alguma coisa, isso é ok, eu vou apenas adicionar um "catch (Exception ignorado) {}" e isso é tudo

Assim, indo com o seu exemplo, que é uma má ideia, nesse caso, porque você está pegando e ignorando todas exceções. Se você estivesse pegando única EInfoFromIrrelevantSourceNotAvailable e ignorá-lo, isso seria ótimo, mas você não é. Você também está ignorando ENetworkIsDown, que pode ou não ser importante. Você está ignorando ENetworkCardHasMelted e EFPUHasDecidedThatOnePlusOneIsSeventeen, que são quase certamente importante.

Um bloco catch vazio não é um problema se ele está configurado para único problema (e ignorar) exceções de certos tipos que você sabe ser sem importância. As situações em que é uma boa ideia para suprimir e ignorar silenciosamente todas exceções, sem parar para examiná-los primeiro para ver se eles estão esperado / normal / irrelevante ou não, são extremamente raros.

Há situações em que você pode usá-los, mas eles devem ser muito pouco frequente. Situações em que eu poderia usar um incluem:

  • logging exceção; dependendo do contexto, você pode querer uma exceção não tratada ou mensagem postada em seu lugar.

  • looping situações técnicas, como renderização ou de processamento de som ou uma chamada de retorno caixa de listagem, onde o próprio comportamento vai demonstrar o problema, lançando uma exceção só vai ficar no caminho, e registrando a exceção provavelmente só irá resultar em 1000, de "falhou ao XXX" mensagens.

  • programas que não pode falhar, embora eles ainda deve ser pelo menos o registo algo.

para a maioria das aplicações WinForms, eu descobri que basta ter um try único para cada entrada do usuário. Eu uso os seguintes métodos: (Alertbox é apenas um invólucro MessageBox.Show rápida)

  public static bool TryAction(Action pAction)
  {
     try { pAction(); return true; }
     catch (Exception exception)
     {
        LogException(exception);
        return false;
     }
  }

  public static bool TryActionQuietly(Action pAction)
  {
     try { pAction(); return true; }
     catch(Exception exception)
     {
        LogExceptionQuietly(exception);
        return false;
     }
  }

  public static void LogException(Exception pException)
  {
     try
     {
        AlertBox(pException, true);
        LogExceptionQuietly(pException);
     }
     catch { }
  }

  public static void LogExceptionQuietly(Exception pException)
  {
     try { Debug.WriteLine("Exception: {0}", pException.Message); } catch { }
  }

Em seguida, cada manipulador de eventos pode fazer algo como:

  private void mCloseToolStripMenuItem_Click(object pSender, EventArgs pEventArgs)
  {
     EditorDefines.TryAction(Dispose);
  }

ou

  private void MainForm_Paint(object pSender, PaintEventArgs pEventArgs)
  {
     EditorDefines.TryActionQuietly(() => Render(pEventArgs));
  }

Teoricamente, você poderia ter TryActionSilently, o que pode ser melhor para a prestação de chamadas de modo que uma exceção não gera uma quantidade infinita de mensagens.

Você nunca deve ter um bloco catch vazio. É como esconder um erro que você conhece. No mínimo você deve escrever uma exceção para um arquivo de log para rever mais tarde, se você está pressionado pelo tempo.

Se você não sabe o que fazer no bloco catch, você pode apenas registrar esta exceção, mas não deixá-lo em branco.

        try
        {
            string a = "125";
            int b = int.Parse(a);
        }
        catch (Exception ex)
        {
            Log.LogError(ex);
        }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top