En .NET, ¿hay alguna ventaja en un try / catch donde el catch simplemente vuelve a salir [duplicado]?

StackOverflow https://stackoverflow.com/questions/1207172

  •  05-07-2019
  •  | 
  •  

Pregunta

  

Posible duplicado:
   ¿Por qué capturar y volver a emitir la excepción en C #?

A veces me encuentro con un código C # que se ve así:

        try
        {
            // Some stuff
        }
        catch (Exception e)
        {
            throw e;
        }

Entiendo que es posible hacer algo como registrar el mensaje de excepción y luego volver a emitirlo. Estoy hablando de una trampa que solo vuelve a salir la excepción. No veo un punto para esto. Tengo tres preguntas:

1) ¿Hay alguna ventaja en esto

2) ¿Hace esto lento el código en absoluto?

3) ¿Haría alguna diferencia si el bloque de captura fuera el siguiente:

        catch (Exception)
        {
            throw;
        }
¿Fue útil?

Solución

Esto vuelve a lanzar la misma excepción exacta :

    catch (Exception)
    {
        throw;
    }

Mientras que esto vuelve a emitir la excepción sin el seguimiento de pila original:

    catch (Exception e)
    {
        throw e;
    }

A menudo hay una buena razón para lanzar ; , ya que puede registrar la excepción o hacer otras cosas antes de volver a generar la excepción. No tengo conocimiento de ninguna buena razón para throw e; , ya que borrará la valiosa información de seguimiento de la pila.

Otros consejos

No si no hace nada más en la captura ... Pero esto se usa a menudo para hacer otras cosas en la captura, como el registro u otro tipo de procesamiento de excepciones, antes de volver a generarla.

Utilizo esa técnica para poder poner un punto de interrupción en el lanzamiento al depurar. A veces lo quito después de que termine ...

La principal diferencia es que el seguimiento de la pila de la excepción se modificará para mostrar que se originó en la ubicación del try-catch en el primer ejemplo.

El segundo ejemplo mantiene el seguimiento de la pila.

¿Hay alguna ventaja

Generalmente hablando no. Todo lo que hará este patrón es restablecer la traza de la pila al punto del nuevo lanzamiento. Esto solo hará que sea más difícil para los desarrolladores rastrear el origen del problema

¿Ralentiza el código en absoluto?

¿En absoluto? Posiblemente. ¿Ralentizarlo por alguna diferencia medible? No.

¿Habría alguna diferencia si el bloque de captura fuera el siguiente?

Sí, esa captura es esencialmente completamente redundante. Reenviará la excepción que mantendrá el seguimiento de la pila original y no tendrá un impacto visible en su aplicación.

1 - No veo ninguna ventaja en absoluto. Si no está manejando la excepción, deje el try / catch off. El otro problema con este ejemplo es que no está lanzando la excepción real, sino una nueva.

2 - sí, pero a menos que esté en un gran bucle de código repetido, es probable que no note una diferencia.

3 - Sí. En el primer ejemplo, estás jugando con tu pila de llamadas. Este ejemplo mantiene la pila intacta al burbujear la excepción, en lugar de lanzar una nueva.

Si realmente no estás haciendo nada más, solo he encontrado una ventaja: puedes poner un punto de interrupción en la línea throw . Lo hace muy específico (en lugar de solo romper cada vez que se lanza ese tipo de excepción).

Solo lo haría mientras depuraba, y luego revertiría el código.

Escribí una prueba rápida para mostrar las diferencias. Aquí está el código de prueba:

try
{
    var broken = int.Parse("null");
}
catch (Exception ex1)
{
    System.Diagnostics.Trace.WriteLine(ex1.ToString());
}

try
{
    try
    {
        var broken = int.Parse("null");
    }
    catch (Exception)
    {
        throw;
    }
}
catch (Exception ex2)
{
    System.Diagnostics.Trace.WriteLine(ex2.ToString());
}

try
{
    try
    {
        var broken = int.Parse("null");
    }
    catch (Exception ex3)
    {
        throw ex3;
    }
}
catch (Exception ex4)
{
    System.Diagnostics.Trace.WriteLine(ex4.ToString());
}

Al ejecutar esto, obtengo el siguiente resultado:

A first chance exception of type 'System.FormatException' occurred in mscorlib.dll
System.FormatException: Input string was not in a correct format.
   at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
   at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
   at System.Int32.Parse(String s)
   at QuickTests.Program.Main(String[] args) in C:\Projects\Test\QuickTests\Program.cs:line 18
A first chance exception of type 'System.FormatException' occurred in mscorlib.dll
A first chance exception of type 'System.FormatException' occurred in QuickTests.exe
System.FormatException: Input string was not in a correct format.
   at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
   at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
   at System.Int32.Parse(String s)
   at QuickTests.Program.Main(String[] args) in C:\Projects\Test\QuickTests\Program.cs:line 33
A first chance exception of type 'System.FormatException' occurred in mscorlib.dll
A first chance exception of type 'System.FormatException' occurred in QuickTests.exe
System.FormatException: Input string was not in a correct format.
   at QuickTests.Program.Main(String[] args) in C:\Projects\Test\QuickTests\Program.cs:line 49

Notarás que las dos primeras excepciones funcionan de la misma manera. Por lo tanto, " lanzar; " no cambia nada en cuanto a la excepción que sube la pila. Sin embargo, " lanzar ex3; " hace que la excepción informada sea diferente, cambiando el seguimiento de la pila para la excepción.

A menudo es bueno para el registro. Además, si omite el argumento en el relanzamiento, entonces no altera el seguimiento de la pila de e.

Algunas veces, usted desea permitir a través de ciertos tipos, por ejemplo. Aquí hay un procesamiento especial para todo menos FooException:

try
{
    // ...
}
catch (FooException)
{
    throw;
}
catch (Exception ex)
{
    // handle differently, like wrap with a FooException
    throw new FooException("I pitty the Foo.", ex);
}

Claro.

La mayoría de las veces, desea registrar la excepción antes de lanzarla, y tal vez registrar algunos valores variables del método.

Sin embargo, solo atraparlo para lanzarlo no te gana mucho.

Así, no. Sin embargo, es posible que desee hacer esto:

catch (Exception ex)
{
     LogException(ex);
     throw;
}

Donde LogException () es una clase personalizada que, erm, registra la excepción o envía por correo electrónico una alerta o algo así.

Creo que el punto es garantizar que solo se genere un TIPO de excepción. Es un IMHO bastante malo anti-patrón

por ejemplo

try
{
    throw XYZ();
}
catch(Exception e)
{
    throw e;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top