practices practice handling exceptions example ejemplo custom best c# exception

practice - throw c# ejemplo



Clase de excepción básica de captura en.NET (16)

Sigo oyendo eso

catch (Exception ex)

Sin embargo, es una mala práctica, a menudo lo uso en controladores de eventos donde una operación puede ir a la red, lo que permite la posibilidad de muchos tipos diferentes de fallas. En este caso, capturo todas las excepciones y visualizo el mensaje de error al usuario en un cuadro de mensaje.

¿Esto se considera una mala práctica? No hay nada más que pueda hacer con la excepción: no quiero detener la aplicación, el usuario necesita saber qué sucedió y estoy en el nivel superior de mi código. ¿Qué más debería estar haciendo?

EDITAR:

La gente dice que debería mirar a través de la pila de llamadas y manejar los errores específicamente, porque, por ejemplo, una excepción de StackOverflow no se puede manejar de manera significativa. Sin embargo, detener el proceso es el peor resultado, quiero evitarlo a toda costa. Si no puedo manejar un StackOverflow, que así sea; el resultado no será peor que no captar excepciones, y en el 99% de los casos, informar al usuario es la opción menos mala por lo que a mí respecta.

Además, a pesar de mis mejores esfuerzos para resolver todas las posibles excepciones que se pueden lanzar, en una gran base de código, es probable que extrañaría algo. Y para la mayoría de ellos, la mejor defensa es informar al usuario.


Creo que el cartel se refiere al manejo de excepciones como este:

try {something} catch (SqlException) {do stuff} catch (Exception) {do other stuff}

La idea aquí es que primero desee detectar los errores más específicos (como SqlException) y manejarlos de forma adecuada, en lugar de confiar siempre en la Excepción general catch-all.

La sabiduría convencional dice que esta es la forma correcta de hacer un manejo de excepciones (y que un solo Catch (Exception ex) es malo). En la práctica, este enfoque no siempre funciona, especialmente cuando se trabaja con componentes y bibliotecas escritos por otra persona.

Estos componentes arrojarán a menudo un tipo diferente de excepción en la producción de la que esperaba su código según el comportamiento del componente en su entorno de desarrollo, aunque el problema subyacente sea el mismo en ambos entornos. Este es un problema increíblemente común en ASP.NET, y a menudo me ha llevado a usar un bloque Catch (Exception ex) desnudo, que no le importa qué tipo de excepción se lanza.

El manejo estructurado de excepciones es una gran idea en teoría. En la práctica, puede ser una gran idea dentro del dominio de código que usted controla. Una vez que introduces cosas de terceros, a veces no funciona muy bien.


Cuando yo veo

catch (Exception ex)

mi mano comienza a buscar a tientas un martillo. Casi no hay excusas para atrapar Excepción base. Solo casos válidos que me vienen a la mente son:
1) El componente de un tercero arroja la excepción (maldito sea su autor)
2) Manejo de excepciones de nivel superior (como último recurso) (por ejemplo, manejar excepciones "no controladas" en la aplicación WinForms)

Si encuentra un caso donde pueden ocurrir muchos tipos diferentes de excepciones, es una buena señal de mal diseño.

No estaría de acuerdo con Armin Ronacher. ¿Cómo te comportarías si surgiera la excepción de ? Intentar realizar acciones adicionales puede llevar a consecuencias aún peores. Captura la excepción solo si puedes manejarla de manera significativa y segura. Catching System.Exception para cubrir el rango de posibles excepciones es terriblemente incorrecto. Incluso cuando lo vuelves a lanzar.


Debes ver las excepciones relacionadas con lo que estás haciendo. Si observas los métodos que llamas, verás qué excepciones arrojan y quieres ser más específico para ellos. Debe tener acceso para saber qué excepciones pueden arrojar los métodos que llama y manejarlos de manera adecuada.

Y ... mejor que tener un gran intento de captura, haz tu intento y atrapa dónde necesitas la captura.

try { myThing.DoStuff(); } catch (StuffGoneWrongException ex) { //figure out what you need to do or bail }

Quizás no esté tan lleno, pero depende de lo que estés haciendo. Recuerde, el trabajo no es solo compilarlo y ponerlo en el escritorio de alguien, quiere saber qué se rompe si algo sucedió y cómo solucionarlo. (Inserte una diatriba sobre el rastreo aquí)


Encuentro que los argumentos de que las capturas genéricas siempre son malas son demasiado dogmáticas. Ellos, como todo lo demás, tienen un lugar.

Ese lugar no es tu código de biblioteca, ni las clases que desarrollas a medida para tu aplicación. Ese lugar es, como muchos han mencionado, el nivel más alto de la aplicación, donde si se produce alguna excepción, es muy probable que sea inesperado.

Aquí está mi regla general (y como todas las reglas, está diseñada para romperse cuando sea apropiado):

Utilizo clases y bibliotecas personalizadas para la mayoría del levantamiento en una aplicación. Esta es la arquitectura básica de la aplicación, realmente básica. Estos tipos intentan manejar la mayor cantidad posible de excepciones y, si realmente no pueden continuar, lanzan el tipo más específico disponible de vuelta a la IU.

En la interfaz de usuario, tiendo a captar siempre todo de los controladores de eventos. Si hay una expectativa razonable de detectar una excepción específica, y puedo hacer algo al respecto, entiendo la excepción específica y la manejo con gracia. Sin embargo, esto debe venir antes de atrapar todo, ya que .NET solo usará el primer controlador de excepciones que coincida con su excepción. (¡Ordena siempre de lo más específico a lo más genérico!)

Si no puedo hacer nada respecto a la excepción que no sea el error de salida (por ejemplo, la base de datos está fuera de línea), o si la excepción es realmente inesperada, catch all lo tomará, lo registrará y fallará rápidamente, con un mensaje de error general mostrado al usuario antes de morir. (Por supuesto, hay ciertas clases de errores que casi siempre fallan sin gracia: OutOfMemory, , etc. Tengo la suerte de no haber tenido que lidiar con aquellos en el código de nivel de producto ... hasta ahora!)

Atrapar todo tiene su lugar. Ese lugar no es para esconder la excepción, ese lugar no es para tratar de recuperarlo (porque si no sabes lo que atrapaste, cómo puedes recuperarlo), ese lugar no es para evitar que los errores se muestren al usuario mientras se permite su aplicación para continuar ejecutándose en un estado desconocido y malo.

Catch all''s place es ser el último recurso, una trampa para garantizar que, si algo pasa a través de sus defensas bien diseñadas y bien protegidas, que como mínimo se haya registrado correctamente y se pueda realizar una salida limpia. Es una mala práctica si no tienes defensas bien diseñadas y bien protegidas en los niveles más bajos, y es una práctica muy mala en los niveles inferiores, pero hecho como último recurso es (en mi opinión) no solo aceptable. , pero a menudo lo correcto para hacer.


Es una mala práctica en el sentido de que no debes hacerlo en todas partes.

En este caso, lo consideraría la única solución razonable ya que su excepción podría ser realmente cualquier cosa. La única mejora posible sería agregar controladores adicionales antes de capturar todo para casos de error específicos donde podría hacer algo con respecto a la excepción.


Está perfectamente bien si vuelves a plantear excepciones que no puedes manejar correctamente. Si solo detecta las excepciones, podría ocultar errores en el código que no espera. Si detecta excepciones para mostrarlas (y elude el comportamiento de troquelado e impresión de rastreo a stderr) eso es perfectamente aceptable.


He estado trabajando bastante con excepciones, y aquí está la estructura de implementación que estoy siguiendo actualmente:

  1. Atenúe todo a Nothing / String.Empty / 0 etc. fuera de Try / Catch.
  2. Inicializa todo dentro de Try / Catch a los valores deseados.
  3. Captura primero las excepciones más específicas, por ejemplo, FormatException pero deja en la base el manejo de excepciones como último recurso (puedes tener múltiples bloques catch, recuerda)
  4. Casi siempre tirar excepciones
  5. Deje que Application_Error sub en global.asax maneje los errores con elegancia, por ejemplo, invoque una función personalizada para registrar los detalles del error en un archivo y redirija a alguna página de error
  6. Mata a todos los objetos que Dim''d en un bloque Finally

Un ejemplo en el que pensé que era aceptable no procesar una excepción "correctamente" recientemente fue trabajar con una cadena GUID (strGuid) pasada a través de HTTP GET a una página. Podría haber implementado una función para verificar la validez de la cadena GUID antes de llamar a New Guid (strGuid), pero me pareció bastante razonable:

Dim myGuid As Guid = Nothing Try myGuid = New Guid(strGuid) ''Some processing here... Catch ex As FormatException lblError.Text = "Invalid ID" Catch ex As Exception Throw Finally If myGuid IsNot Nothing Then myGuid = Nothing End If End Try


La mala práctica es

catch (Exception ex){}

y variantes:

catch (Exception ex){ return false; }

etc.

Capturar todas las excepciones en el nivel superior y pasarlas al usuario (ya sea registrándolas o mostrándolas en un buzón, dependiendo de si está escribiendo un servidor o una aplicación cliente), es exactamente lo correcto que hacer.


Lo importante es comprender el camino de las excepciones a través de su aplicación, y no solo arrojarlas o atraparlas arbitrariamente. Por ejemplo, ¿qué pasa si la excepción que capta es Out-Of-Memory? ¿Estás seguro de que tu cuadro de diálogo se mostrará en ese caso? Pero está bien definir un punto de excepción de última instancia y decir que nunca querrá que los errores se propaguen más allá de ese punto.


No; en ese caso, si no quieres detener el programa, no hay nada más que puedas hacer y en el nivel superior está el lugar correcto para hacerlo, siempre y cuando estés iniciando sesión correctamente y no escondiéndolo en la sonrisa de esperanza.


Respondo: "Sin embargo, detener el proceso es el peor resultado ..."

Si puede manejar una excepción ejecutando un código diferente (usando try / catch como flujo de control), reintentar, esperar y reintentar, reintentar con una técnica diferente pero equivalente (es decir, método alternativo), entonces hágalo de todos modos.

También es bueno reemplazar y registrar mensajes de error, a menos que sea ese "contacto con el administrador" pseudo-cortés-pasivo-agresivo (cuando sabes que no hay administrador y si el administrador no puede hacer nada al respecto). ) Pero después de hacer eso, la aplicación debe finalizar, es decir, el mismo comportamiento que obtiene con una excepción no controlada.

Por otro lado, si tiene la intención de manejar la excepción devolviendo al usuario a un hilo de código que potencialmente ha hecho añicos su estado, yo diría que es peor que finalizar la aplicación y dejar que el usuario vuelva a comenzar. ¿Es mejor para el usuario reiniciar al principio o mejor para dejar que el usuario destruya los datos?

Si recibo una excepción inesperada en el módulo que determina a qué cuentas puedo retirar dinero, ¿realmente deseo registrar e informar una excepción y devolver al usuario a la pantalla de retirar dinero? ¡Por todo lo que sabemos, acabamos de concederle el derecho de retirar dinero de todas las cuentas!


Sí, está bien capturar la Execption base en el nivel superior de la aplicación , que es lo que está haciendo.

Las reacciones fuertes que está recibiendo probablemente se deba a que en cualquier otro nivel , casi siempre es incorrecto atrapar la excepción Base. Específicamente en una biblioteca sería una muy mala práctica.


Tiene todo el sentido capturar la excepción al más alto nivel en su código. Capturar el tipo de excepción base está bien siempre que no necesite hacer ninguna lógica diferente basada en el tipo de la excepción.

Además, asegúrese de mostrar un mensaje de error general y amigable y no mostrar el mensaje de la excepción real. Eso puede conducir a vulnerabilidades de seguridad.


Todo esto es bueno para capturar excepciones que pueda manejar. Pero a veces también sucede que debido a un entorno inestable o que los usuarios solo hacen el proceso correctamente, la aplicación se encuentra con una excepción inesperada. Que no ha sido incluido o manejado en el código. ¿Hay alguna manera de capturar la excepción no controlada desde el archivo app.config y muestra un error común?

También coloca ese mensaje de excepción de detalles en un archivo de registro.


Usamos Catch ex como Exception (variante VB.Net) bastante. Lo registramos y examinamos nuestros registros regularmente. Localice las causas y resuelva.

Creo que Catch ex as Exception es completamente aceptable una vez que se trata de un código de producción, Y usted tiene una manera general de manejar excepciones desconocidas con gracia. Personalmente, no coloco la captura genérica hasta que complete un módulo / nueva funcionalidad y manejo especializado para cualquier excepción que encuentre en las pruebas. Eso parece ser lo mejor de ambos mundos.


muchas veces la excepción se atrapa en los recursos libres, no es importante si se (arroja) la excepción. en estos casos puedes evitar intentar atrapar:

1) para objeto desechable puede usar palabra clave "using": using (SqlConnection conn = new SqlConnection (connStr)) {// code} una vez que está fuera del alcance de uso (normalmente o por una declaración de devolución o por excepción), Dispsose el método se llama automáticamente al objeto. en otras palabras, es como intentar / finalmente construir.

2) en asp.net, puede interceptar el evento Error o UnLoad de la página para liberar su recurso.

¡Espero ayudarte!