Pregunta

La comprensión de la diferencia entre tiro ex y tiro , ¿por qué el StackTrace original en conserva en este ejemplo:

    static void Main(string[] args)
    {
        try
        {
            LongFaultyMethod();
        }
        catch (System.Exception ex)
        {
            Console.WriteLine(ex.StackTrace);
        }
    }

    static void LongFaultyMethod()
    {
        try
        {
            int x = 20;
            SomethingThatThrowsException(x);
        }
        catch (Exception)
        {
            throw;
        }
    }

    static void SomethingThatThrowsException(int x)
    {
        int y = x / (x - x);
    }

Pero no en éste:

    static void Main(string[] args)
    {
        try
        {
            LongFaultyMethod();
        }
        catch (System.Exception ex)
        {
            Console.WriteLine(ex.StackTrace);
        }
    }

    static void LongFaultyMethod()
    {
        try
        {
            int x = 20;
            int y = x / (x - 20);
        }
        catch (Exception)
        {
            throw;
        }
    }

El segundo escenario se produce el mismo resultado que tiro ex lo haría?

En ambos casos, uno espera ver el número de línea en la que y se inicializa.

¿Fue útil?

Solución

No estoy seguro de si esta limitación se encuentra dentro del lenguaje C #, la CLI o la implementación de Microsoft de estos, pero el segundo ejemplo es un caso en el que se requiere una llamada explícita a Exception.InternalPreserveStackTrace como se documenta en el siguiente post. Dado que se internal este método, por lo general tiene que ser llamado a través de la reflexión. Los problemas de rendimiento que participan en este pueden ser casi completamente aliviados mediante la creación de un Action<Exception> para la llamada, como se muestra al final de esta respuesta.

Referencia: Regeneración de excepciones y preservar el seguimiento de la pila de llamadas completa

Editar Después de reexaminar ECMA-335 de partición que §12.4.2 (manejo de excepciones) y la partición III §4.24 (volver a lanzar), ahora creo que el comportamiento que está viendo es un error semántico en el CLR (ejecución de la CLI de Microsoft). La referencia solamente al comportamiento específico es "Un rethrow no cambia el seguimiento de la pila en el objeto." En el caso aquí descrito, el volver a lanzar es, de hecho, alterar el seguimiento de la pila, haciendo que el PreserveStackTrace hackear una solución para un defecto de conocimientos CLR.

static void LongFaultyMethod() 
{ 
    try 
    { 
        int x = 20; 
        int y = x / (x - 20); 
    } 
    catch (Exception ex) 
    { 
        PreserveStackTrace(ex); // <-- add this line
        throw; 
    } 
} 

PreserveStackTrace aquí es una optimización de la de que la entrada de blog:

private static readonly Action<Exception> _internalPreserveStackTrace =
    (Action<Exception>)Delegate.CreateDelegate(
        typeof(Action<Exception>),
        typeof(Exception).GetMethod(
            "InternalPreserveStackTrace",
            BindingFlags.Instance | BindingFlags.NonPublic));

public static void PreserveStackTrace(Exception e)
{
    _internalPreserveStackTrace(e);
}

Otros consejos

Debido a que en el segundo ejemplo, se le Regeneración de excepción del mismo método. En primer lugar su lanzada desde diferentes eso es por qué método. En un alcance método, seguimiento de la pila puede ser único.

Haz lo siguiente, la mejor manera es envolver siempre una excepción dentro de una nueva excepción, por lo que se pueden ver la profundidad excepción.

  

"Si ha sido volver a lanzar en emitido en el   mismo método (seguimiento de la pila excepción   sólo tiene una línea de información del número de   por método, nunca se ve seguimiento de la pila   que en el Método A, en la línea número 2   excepción fue lanzada y luego en el mismo   Método A, se relanza de la línea   el número 17, que sólo contendrá última   número de línea desde donde fue excepción   relanza "

try        
{            
   int x = 20;            
   int y = x / (x - 20);        
}        
catch (Exception ex)        
{            
   // do something here.. like log or something
   throw new Exception("Internal Exception", ex);        
}

Estoy sorprendido por tantos comentarios que no leen mi comentario !! Escribí en el comentario que probablemente debería registrar esto de manera segura , hay varias razones, si las come de código de nivel superior hasta una excepción y que no sabe qué y dónde fue arrojado excepción, el registro le ayuda a excepción intersecan !! !

Si no es necesario para iniciar la sesión, entonces no detectar la excepción.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top