2009-01-10 26 views
8

Si todo lo que quiero hacer es arrojar la excepción a un nivel cuando ocurre?C# ¿Necesito TRY/CATCH para lanzar?

private void TryCatch() 
{ 
    try 
    { 
     foo(); 
    } 
    catch (Exception ex) 
    { 
     throw; 
    } 
} 

private void NoTryCatch() 
{ 
    foo(); 
} 

¿No son estos dos métodos lo mismo?

Si se produce una excepción en TryCatch, se lanzará un nivel y si se produce una excepción en NoTryCatch, la excepción también se lanzará a un nivel.

Esta pregunta surgió después de usar ReSharper y al notar que sugería eliminar el bloque try/catch porque era redundante.

Respuesta

1

Estos dos métodos son esencialmente los mismos. En este caso, ReSharper estaba en lo correcto con su sugerencia.

3

No, no necesita la captura de prueba. La única razón por la que desearía usar la primera función es si desea realizar algún registro o liberar recursos antes de manejar la función más arriba.

0

ReSharper es correcto. A menos que realmente pretenda atrapar y hacer algo acerca de una excepción, no tiene sentido incluir un bloque try..catch.

+0

A menos que necesite el bloque finally para hacer algún trabajo de limpieza. –

+1

@Fred: Eso sería 'try..finally' luego no' try..catch', ¿verdad? – AnthonyWJones

0

Sí, el bloque try catch es redundante. La pila simplemente se desenrollará hasta que se encuentre un try/catch para manejar la excepción.

0

Si todo lo que hace es volver a lanzar la excepción, no necesita el bloque try/catch. En general, solo debe detectar excepciones cuando puede manejarlas. De lo contrario, permita que se propaguen hacia arriba.

19

Sí, esos métodos son prácticamente iguales (*). La única diferencia es que es fácil poner un punto de quiebre en el primero. Siempre iba con el segundo, a menos que realmente tuviera que romper allí y solo allí (en lugar de lanzar inmediatamente cualquier excepción de ese tipo, lo que sería fácil). Incluso si alguna vez utilicé el primero, lo volvería a poner en el segundo formulario antes de confirmar el código.

(*) Es posible que existan algunas diferencias en cuanto a la forma en que el JIT las maneja. El primero terminará con más IL, lo que afectará las oportunidades de alineación, etc.

EDITAR: No me puedo resistir a un poco de micro-benchmarking. Parece que try/catch/tiro tiene efectos más desagradables en el rendimiento que acaba de desactivación de procesos en línea:

using System; 
using System.Diagnostics; 
using System.Runtime.CompilerServices; 

public class Test 
{ 
    const int Iterations = 1000000000; 

    static void Main() 
    { 
     Stopwatch sw; 

     sw = Stopwatch.StartNew(); 
     for (int i=0; i < Iterations; i++) 
     { 
      SimpleMethod(); 
     } 
     sw.Stop(); 
     Console.WriteLine("Simple method: {0}", sw.ElapsedMilliseconds); 

     sw = Stopwatch.StartNew(); 
     for (int i=0; i < Iterations; i++) 
     { 
      NoInlining(); 
     } 
     sw.Stop(); 
     Console.WriteLine("No inlining: {0}", sw.ElapsedMilliseconds); 

     sw = Stopwatch.StartNew(); 
     for (int i=0; i < Iterations; i++) 
     { 
      TryCatchThrow(); 
     } 
     sw.Stop(); 
     Console.WriteLine("try/catch/throw: {0}", sw.ElapsedMilliseconds); 
    } 

    static void SimpleMethod() 
    { 
     Foo(); 
    } 

    [MethodImpl(MethodImplOptions.NoInlining)] 
    static void NoInlining() 
    { 
    } 

    static void TryCatchThrow() 
    { 
     try 
     { 
      Foo(); 
     } 
     catch (Exception) 
     { 
      throw; 
     } 
    } 

    static void Foo() {} 
} 

compilar con /o+ /debug-

resultados (tres carreras):

método simple: 504, 495, 489
n procesos en línea: 2977, 3060, 3019
try/catch/tirar: 5274, 4543, 5145

+0

Creo que cualquier intento/captura evitará la alineación. Investigando ... – JaredPar

+0

Esa fue mi suposición también, aunque no tenía la energía para la investigación. No es que haya nada que impida que el JIT advierta que el try/catch es redundante en este caso, sospecho, y quitándolo ... –

+0

No se puede encontrar nada para respaldar mi afirmación. Creo que fue tirar o try/catch previene en línea. Sospecho que en realidad puede ser tirada contra captura. – JaredPar

0

Algo pensé, pero No estaba seguro al 100%, así que fui a comprobar. Tenía razón, a veces.

Aparentemente, si vuelve a lanzar la excepción, que es lo que está haciendo su código, podría terminar cambiando el stack-trace. En primer lugar, si escribiera throw ex; que restablecería el stack-trace. En segundo lugar, incluso al escribir throw; también puede haber casos en los que falta información. Vea esto article y algunos user comments haciendo clic en él.

Por supuesto, la mayoría de estos problemas están relacionados con el trazado de pila y los números de línea, que son importantes, pero pensé que también afectaría el rendimiento, no solo por la alineación (o la falta de ella), sino también debido a toda la excepción de atrapar y tirar por encima, pero no encontré nada concreto en esto.

1

Realmente no son lo mismo. Throw en sí mismo o throw ex lío con la información de seguimiento de la pila y puede dificultar la depuración.

La mejor razón para capturar una excepción es añadir contexto a la traza de la pila, como:

try { 
    Foo(); 
} 
catch (Exception e) { 
    throw new BetterException("I did something slightly silly", e); 
} 
Cuestiones relacionadas