programacion - propiedades de las excepciones en c#
¿Cómo lanzar una excepción sin restablecer el seguimiento de pila? (5)
¿Está detectando excepciones que luego desea filtrar con más cuidado, para poder cambiar de opinión, decidir no manejarlas y volver a hacerlas?
Si quieres tener mucho cuidado con esto, no es realmente una buena idea. Es mejor nunca atrapar la excepción en primer lugar. La razón es que un controlador de try/catch
no debe tomar la decisión de ejecutar bloques anidados finally
para las excepciones que no espera ver. Por ejemplo, si hay una NullReferenceException
, probablemente sea una muy mala idea continuar ejecutando cualquier código, ya que probablemente cause otra excepción similar. Y finally
bloques son solo código, como cualquier otro código. Tan pronto como se detecte una excepción por primera vez, se ejecutará finally
cualquier bloque en la pila debajo del try/catch
, momento en el cual es demasiado tarde; se puede generar otra excepción, y esto significa que la excepción original se ha perdido.
Esto implica (en C #) que debe escribir con cuidado un controlador de catch
separado para todos los tipos de excepción que desea capturar. También implica que solo puede filtrar por tipo de excepción. A veces es un consejo muy difícil de seguir.
Debería ser posible filtrar las excepciones de otras maneras, pero en C # no lo es. Sin embargo, es posible en VB.NET, y el BCL mismo aprovecha esto al tener una pequeña cantidad de código escrito en VB.NET para que pueda filtrar las excepciones de una manera más conveniente.
Aquí hay una explicación detallada, con un ejemplo de código VB.NET, del blog del equipo de CLR.
Esta es una pregunta de seguimiento para ¿Hay alguna diferencia entre “lanzar” y “lanzar ex” ?
¿hay una manera de extraer un nuevo método de manejo de errores sin restablecer el seguimiento de la pila?
[EDITAR] Intentaré el "método interno" y otra answer proporcionada por Earwicker y veré cuál puede funcionar mejor para marcar una respuesta.
Con .NET Framework 4.5 ahora hay un ExceptionDispatchInfo que admite este escenario exacto. Permite capturar una excepción completa y volver a generarla en otro lugar sin sobrescribir el seguimiento de pila contenido.
Ejemplo de código debido a solicitud en comentario
using System.Runtime.ExceptionServices;
class Test
{
private ExceptionDispatchInfo _exInfo;
public void DeleteNoThrow(string path)
{
try { File.Delete(path); }
catch(IOException ex)
{
// Capture exception (including stack trace) for later rethrow.
_exInfo = ExceptionDispatchInfo.Capture(ex);
}
}
public Exception GetFailure()
{
// You can access the captured exception without rethrowing.
return _exInfo != null ? _exInfo.SourceException : null;
}
public void ThrowIfFailed()
{
// This will rethrow the exception including the stack trace of the
// original DeleteNoThrow call.
_exInfo.Throw();
// Contrast with ''throw GetFailure()'' which rethrows the exception but
// overwrites the stack trace to the current caller of ThrowIfFailed.
}
}
No desea crear una nueva excepción con el seguimiento de pila original. Eso es engañoso, ya que el seguimiento de la pila no creó la nueva excepción.
Sin embargo, puede colocar la excepción original en su nueva excepción como "InnerException". ¿Haría eso lo que buscas?
No estoy seguro de si te refieres a eso, pero mi sugerencia en tu otra pregunta fue abordar esto.
Si su manejador devuelve un valor booleano si la excepción fue manejada o no, puede usar esto en su cláusula catch:
catch (Exception ex) {
if (!HandleException(ex)) {
throw;
}
}
Sí; Para eso es la propiedad InnerException.
catch(Exception ex)
{
throw new YourExceptionClass("message", ex);
}
Esto le permitirá agregar su propia lógica, luego lanzar su propia clase de excepción. El StackTrace de la instancia de YourExceptionClass será desde dentro de este bloque de código, pero la InnerException será la excepción que capturó, con el StackTrace que tenía antes.