¿Son los bloques Try / Catch anidados una mala idea?

81

Digamos que tenemos una estructura como esta:

Try
  ' Outer try code, that can fail with more generic conditions, 
  ' that I know less about and might not be able to handle

  Try
    ' Inner try code, that can fail with more specific conditions,
    ' that I probably know more about, and are likely to handle appropriately
  Catch innerEx as Exception
    ' Handle the inner exception
  End Try

Catch outerEx as Exception
  ' Handle outer exception
End Try

He visto algunas opiniones de que Tryse desaconseja anidar bloques como este, pero no pude encontrar ninguna razón específica.

¿Es este un código incorrecto? Si es así, ¿por qué?

Goro
fuente
2
No estoy seguro de la precisión del fragmento. Pero no hay un montón de cosas que realmente sepas cuando atrapas Exception. Puede ser cualquier cosa . Considere aprovechar la cláusula When que admite VB.NET.
Hans Passant

Respuestas:

85

Hay ciertas circunstancias en las que son una buena idea, por ejemplo, un intento / captura para todo el método y otro dentro de un bucle, ya que desea manejar la excepción y continuar procesando el resto de una colección.

Realmente, la única razón para hacerlo es si desea omitir el bit con errores y continuar, en lugar de deshacer la pila y perder el contexto. Abrir varios archivos en un editor es un ejemplo.

Dicho esto, las excepciones deberían (como su nombre lo indica) ser excepcionales. Un programa debería manejarlos pero tratar de evitarlos como parte del flujo de ejecución normal. Son computacionalmente costosos en la mayoría de los lenguajes (Python es una excepción notable).

Otra técnica que puede ser útil es detectar tipos de excepción específicos ...

Try
    'Some code to read from a file

Catch ex as IOException
    'Handle file access issues (possibly silently depending on usage)
Catch ex as Exception
    ' Handle all other exceptions.
    ' If you've got a handler further up, just omit this Catch and let the 
    ' exception propagate
    Throw
End Try

También usamos try / catches anidados en nuestras rutinas de manejo de errores ...

    Try
        Dim Message = String.Format("...", )
        Try
            'Log to database
        Catch ex As Exception
            'Do nothing
        End Try

        Try
            'Log to file
        Catch ex As Exception
            'Do nothing
        End Try
    Catch ex As Exception
        'Give up and go home
    End Try
Básico
fuente
7
Iniciar sesión en un hilo en segundo plano es un lugar en el que usaré un intento / captura interno. No quiero que el método termine porque no pudo documentar lo que estaba haciendo.
gooch
@Gooch cierto, también hago eso, lo agregaré a mi respuesta.
Básico
37

En realidad, no creo que haya nada intrínsecamente incorrecto en los bloques Try/ anidados Catch, excepto que pueden ser difíciles de navegar y es probable que sean una señal de que podría hacer una refactorización (el interno Try/ Catchen su propio método, por ejemplo).

Pero quiero abordar este comentario:

' Outer try code, that can fail with more generic conditions, 
' that I know less about and might not be able to handle

Si no sabe cómo manejar las excepciones en una situación particular, créame: no las atrape. Es mejor dejar que su aplicación se bloquee (quiero decir, ya sabe, registrarla ; simplemente no se la trague) que detectar algo de lo que no sabe cómo recuperarse y luego dejar que su aplicación continúe alegremente en su camino en un estado corrupto . El comportamiento será impredecible en el mejor de los casos a partir de ese momento.

Dan Tao
fuente
Eso es verdad. En el momento de capturar la excepción externa, no querría continuar. Estaba pensando más en poder cerrar / reiniciar la aplicación con elegancia y no sorprender al usuario con un "accidente feo"
Goro
10
@Goro: En ese caso, recomendaría un mecanismo de manejo de excepciones en toda la aplicación (por ejemplo, si se trata de WinForms, maneje el Application.UnhandledExceptionevento) en lugar de por método Try/ Catchbloques.
Dan Tao