remarks generate example c# .net exception error-handling

generate - params comments c#



Bloques vacĂ­os de captura (5)

A veces me encuentro con situaciones en las que necesito detectar una excepción si alguna vez se lanza, pero nunca hago nada con ella. En otras palabras, podría ocurrir una excepción pero no importa si lo hace.

Recientemente leí este artículo sobre algo similar: http://c2.com/cgi/wiki?EmptyCatchClause

Esta persona habla de cómo el comentario de

// should never occur

Es un olor de código y nunca debe aparecer en el código. Luego van a explicar cómo el comentario.

// don''t care if it happens

Es completamente diferente y me encuentro con situaciones como esta. Por ejemplo, al enviar un correo electrónico hago algo similar a esto:

var addressCollection = new MailAddressCollection(); foreach (string address in addresses) { try { addressCollection.Add(address); } catch (Exception) { // Do nothing - if an invalid email occurs continue and try to add the rest } }

Ahora, puede pensar que hacer esto es una mala idea, ya que querría volver al usuario y explicar que no se pudieron enviar uno o más mensajes al destinatario. Pero, ¿y si es solo una dirección de CC? Eso es menos importante y es posible que aún desee enviar el mensaje de todos modos, incluso si una de esas direcciones no es válida (posiblemente solo un error tipográfico).

Entonces, ¿tengo derecho a usar un bloque de captura vacío o hay una alternativa mejor que no conozco?


Muchas de las otras respuestas dan buenas razones cuando estaría bien detectar la excepción, sin embargo, muchas clases apoyan formas de no lanzar la Excepción en absoluto.

A menudo, estos métodos tendrán el prefijo Try frente a ellos. En lugar de lanzar una excepción, la función devuelve un valor booleano que indica si la tarea se realizó correctamente.

Un buen ejemplo de esto es Parse vs TryParse

string s = "Potato"; int i; if(int.TryParse(s, out i)) { //This code is only executed if "s" was parsed succesfully. aCollectionOfInts.Add(i); }

Si prueba la función anterior en un bucle y la compara con su equilibrio Parse + Catch, el método TryParse será mucho más rápido.


Si nunca se debe lanzar una excepción, entonces no tiene sentido atraparla: nunca debería suceder y si lo hace, debe conocerla.

Si hay escenarios específicos que pueden causar una falla con la que usted está bien, entonces debería detectar y probar esos escenarios específicos y volver a participar en todos los demás casos, por ejemplo

foreach (string address in addresses) { try { addressCollection.Add(address); } catch (EmailNotSentException ex) { if (IsCausedByMissingCcAddress(ex)) { // Handle this case here e.g. display a warning or just nothing } else { throw; } } }

Tenga en cuenta que el código anterior captura excepciones específicas (si son ficticias) en lugar de capturar Exception . Puedo pensar en muy pocos casos en los que es legítimo capturar Exception en lugar de capturar algún tipo de excepción específica que esperas que se lance.


Tiene toda la razón para usar un bloque de captura vacío si realmente no quiere hacer nada cuando se produce un cierto tipo de excepción. Podría mejorar su ejemplo capturando solo los tipos de excepciones que espera que ocurran y que sepa que es seguro ignorar. Al capturar Exception , puede ocultar errores y hacer que sea más difícil para usted depurar su programa.

Una cosa a tener en cuenta con respecto al manejo de excepciones: hay una gran diferencia entre las excepciones que se usan para señalar una condición de error externa a su programa, que se espera que ocurra al menos algunas veces, y las excepciones que indican un error de programación. Un ejemplo de la primera sería una excepción que indica que no se pudo entregar un correo electrónico porque se agotó el tiempo de espera de la conexión, o no se pudo guardar un archivo porque no había espacio en el disco. Un ejemplo de la segunda sería una excepción que indica que intentó pasar el tipo incorrecto de argumento a un método o que intentó acceder a un elemento de matriz fuera de los límites.

Para el segundo (error de programación), sería un gran error simplemente "tragar" la excepción. Por lo general, lo mejor es registrar un seguimiento de la pila y luego mostrar un mensaje de error que le dice al usuario que ha ocurrido un error interno y que debe enviar sus registros a los desarrolladores (es decir, a usted). O mientras desarrolla, puede hacer que imprima un seguimiento de la pila en la consola y bloquee el programa.

Para el primero (problema externo), no hay ninguna regla sobre lo que es "hacer" lo correcto. Todo depende de los detalles de la aplicación. Si desea ignorar una determinada condición y continuar, hágalo.

EN GENERAL:

Es bueno que estés leyendo libros y artículos técnicos. Puedes aprender mucho de hacerlo. Pero recuerde, a medida que lea, encontrará muchos consejos de personas que dicen que hacer algo así es siempre incorrecto o correcto. A menudo estas opiniones rayan en la religión. NUNCA crea que hacer las cosas de cierta manera es absolutamente "correcto" porque un libro o artículo (o una respuesta en SO ... <cough>) se lo dijo. Hay excepciones a cada regla, y las personas que escriben esos artículos no conocen los detalles de su aplicación. Tú lo haces. Asegúrese de que lo que está leyendo tenga sentido, y si no lo hace, confíe en usted mismo.


Un bloque de captura vacío está bien en el lugar correcto , aunque, por su muestra, yo diría que cetagóricamente NO debe usar catch (Exception) . En su lugar, debería capturar la excepción explícita que espera que ocurra.

La razón de esto es que, si traga todo, también tragará los defectos críticos que no esperaba. Existe una gran diferencia entre "No puedo enviar a esta dirección de correo electrónico" y "su computadora no tiene espacio en el disco". ¡No querrás seguir intentando enviar los próximos 10000 correos electrónicos si te quedas sin espacio en el disco!

La diferencia entre "no debería suceder" y "no importa si sucede" es que, si "no debería suceder", entonces, cuando sucede, ¡no quiere tragarlo en silencio! Si es una condición que nunca esperó que ocurriera, por lo general, desearía que su aplicación se bloquee (o al menos finalice limpiamente y registre lo que sucedió) para que pueda identificar esta condición imposible.


Usar un bloque de captura vacío solo traga la Excepción, siempre lo manejaría, incluso si le está informando que ocurrió una Exception .

Capturar la Exception genérica también es una mala práctica debido a que puede ocultar errores en su aplicación. Por ejemplo, es posible que haya detectado una excepción ArgumentOutOfRange que no sabía que estaba ocurriendo y luego se la tragó (es decir, no he hecho nada con ella).