24

Tengo un código que usa la reflexión para extraer valores de propiedades de un objeto. En algunos casos, las propiedades pueden lanzar excepciones, porque tienen referencias nulas, etc.¿Por qué TargetInvocationException es tratado como no capturado por el IDE?

object result; 
try 
{ 
    result = propertyInfo.GetValue(target, null); 

} 
catch (TargetInvocationException ex) 
{ 
    result = ex.InnerException.Message; 
} 
catch (Exception ex) 
{ 
    result = ex.Message; 
} 

última instancia, el código funciona correctamente, sin embargo, cuando estoy corriendo en el depurador:

Cuando la propiedad se produce una excepción, el IDE cae en el depurador como si la excepción no hubiera sido detectada. Si pulso ejecutar, el programa fluye y la excepción aparece como una excepción de invocación de destino con la excepción real en la propiedad InnerException.

¿Cómo puedo evitar que esto suceda?

Respuesta

28

Esto parece ser "por diseño". Lo que pasa es que es probable que tenga menú Herramientas Opciones → Depuración → general → Habilitar Sólo mi código habilitado.

Como How to: Break on User-Unhandled Exceptions estados:

La depuración excepciones de diálogo muestra una columna adicional (Salto cuando una excepción es el usuario no controlada) cuando "Habilitar Sólo mi código" se activa.

Esencialmente esto significa que cuando la excepción deja el límite de su código (y en este caso, se reduce al código de reflexión de .NET framework), Visual Studio se rompe porque cree que la excepción ha dejado al usuario código. No sabe que volverá al código de usuario más adelante en la pila.

Así que hay dos soluciones: Desactivar Sólo mi código en el menú Herramientas Opciones → Depuración → generalo Retire la casilla de verificación del usuario no controlada de .NET Framework excepciones en el menú DepurarDiálogo Excepciones.

+0

De hecho, esto ayudó: tuve un error de formato de cadena en alguna parte (intenté mostrar un TimeSpan en formato int, en lugar de el número de días) y obtuvo este error Excepción interna: cadena de formato incorrecta. Pero cómo encontrar dónde se realizó este formato. Cuando revisé "Habilitar solo mi código", la excepción no detectada mostró inmediatamente que este era el problema. –

4

EDITAR: Acabo de probar esto por mí mismo, y parece que la reflexión se trata de forma ligeramente diferente. Es posible que desee considerar una llamada de reflexión como el inicio de un nuevo nivel de "gestión" en lo que respecta al depurador: nada atrapa esa excepción antes de que se traduzca y vuelva a lanzarse como TargetInvocationException, por lo que se rompe. No lo hago saber si hay alguna forma de inhibir eso, pero ¿sucede muy a menudo? Si realiza regularmente muchas operaciones que generan excepciones, puede reconsiderar su diseño.


Respuesta original

Ir a la depuración/excepciones ... y ver lo que los ajustes son. Verá este comportamiento si TargetInvocationException (o cualquier elemento superior en la jerarquía) tiene marcada la casilla "Lanzado".

+0

El caso de uso es una "ventana de observación" para las variables que usa mi aplicación. Para poder mostrar al usuario el estado de lo que está sucediendo en la aplicación. Por lo tanto, solo ocurre cuando el usuario solicita que se actualice la ventana del reloj. En tiempo de ejecución no es realmente un problema, ya que la excepción finalmente se atrapa, ¡pero durante el desarrollo es un gran dolor porque no me deja correr! –

+1

¡Mi primera respuesta de Jon Skeet! –

+0

@Jason: Sí, puedo ver que ser un dolor. No sé de qué manera, me temo. Para la mayoría de las situaciones, es probable que sea el comportamiento correcto. –

Cuestiones relacionadas