Código de método principal completamente dentro de try / catch: ¿es una mala práctica?

Usualmente pongo todo mi código de método principal dentro de un bloque try / catch de esta manera:

public static void Main(string[] args) { try { // code } catch (Exception e) { // code } } 

Lo hago por si acaso las excepciones logran salirse del rest de la lógica del progtwig, lo que me permite hacer algo al respecto, como mostrarlo en la consola, registrarlo en un archivo, etc. Sin embargo, me han dicho que esta es una mala práctica

¿Crees que es una mala práctica?

Envolver cualquier pieza de código en un bloque try / catch sin una buena razón es una mala práctica.

En el modelo de progtwigción .NET, las excepciones deben reservarse para casos o condiciones verdaderamente excepcionales. Solo deberías tratar de detectar excepciones de las que realmente puedas hacer algo . Además, casi nunca deberías atrapar la clase System.Exception base (sino que prefieres captar las clases de excepciones derivadas más específicas que puedes manejar). Y si se produce una excepción verdaderamente inesperada durante el curso de la ejecución de su progtwig, en realidad debería bloquearse.

Obviamente, la respuesta “correcta” tendría que hacerse caso por caso, dependiendo de lo que esté sucediendo dentro de // code marcador de posición del // code en tu bloque catch . Pero si está pidiendo una regla general o una “mejor práctica”, siempre debe tener una razón específica para detectar excepciones, no simplemente envolver todo su código en un bloque de try / catch gigante como una cuestión de rutina sin pensarlo. .

Tenga en cuenta que si simplemente está tratando de detectar cualquier excepción no controlada que pueda ocurrir con el propósito de registrar o informar errores, debe usar el evento AppDomain.UnhandledException . Este es un evento solo de notificación, por lo que no le permite manejar esas excepciones, pero es el lugar correcto para implementar su funcionalidad de registro o informe de errores después de que su aplicación se haya bloqueado.


EDITAR: Mientras me ponía al día con mi lectura del excelente blog de Raymond Chen, “The Old New Thing” , noté que recientemente había publicado un artículo sobre un tema similar. Es específico de COM, en lugar de .NET Framework, pero los conceptos generales con respecto al manejo de errores son igualmente aplicables a ambos entornos. Pensé en compartir un par de gems del artículo aquí, en apoyo de mi opinión [aparentemente bastante controvertida].

Históricamente, COM colocó una prueba / excepción gigante alrededor de los métodos de su servidor. Si su servidor encontró lo que normalmente sería una excepción no controlada, el gigante try / except lo atraparía y lo convertiría en el error RPC_E_SERVERFAULT . A continuación, marcó la excepción como manejada, de modo que el servidor permaneció en ejecución, con lo que “mejoró la solidez al mantener el servidor en funcionamiento incluso cuando se encontró con un problema”.

Eso sí, esto fue en realidad un perjuicio.

El hecho de que se haya producido una excepción no controlada significa que el servidor se encontraba en un estado inesperado. Al detectar la excepción y decir “No te preocupes, todo está bien”, terminas dejando un servidor dañado funcionando.

[. . . ]

Capturar todas las excepciones y dejar que el proceso continúe ejecutándose supone que un servidor puede recuperarse de una falla inesperada. Pero esto es absurdo. Usted ya sabe que el servidor está increíblemente bien: ¡se colgó!

Mucho mejor es dejar que el servidor se cuelgue para poder capturar el volcado de fallo en el punto de la falla. Ahora tienes una oportunidad de luchar para descubrir qué está pasando.

Puede [y debería] leer todo el artículo aquí en su blog: cómo desactivar el manejador de excepciones que COM “amablemente” envuelve alrededor de su servidor .

Si estás haciendo lo más inteligente que puedes con el error, es una buena práctica. Para eso es para try / catch.

Si solo está tirando el error (o lo está registrando y tirándolo), especialmente si lo hace independientemente del tipo de excepción, eso se considera una mala práctica.

Esto podría plantear la pregunta: ¿y si lo más inteligente es registrarlo y tirarlo? Quiero decir que sería un caso excepcional. Pero en la práctica, mi código afirmaría lo contrario. Supongo que me entrego a mucha mala práctica.

Estoy de acuerdo con el 90% de lo que dice Cody. Hay algunas situaciones similares al ejemplo de complemento donde es posible que desee capturar excepciones del sistema. Aquí hay otro ejemplo, considere consumir un servicio web de WCF .

Objetivo : consumir el servicio y disponerlo incluso si se encuentra un error. Permita que el error burbujee.

 public static bool DoRemoteWebServiceWork() { bool result; RemoteWebServiceClient client = new RemoteWebServiceClient(); try { result = client.DoWork(); client.Close(); } catch (Exception) { client.Abort(); //dispose throw;//This service is critical to application function. The application should break if an exception is thrown. //could log end point and binding exceptions to avoid ignoring changes to the remote service that require updates to our code. } return result; } 

Objetivo : consumir el servicio y disponerlo incluso si se encuentra un error. Evite que el error burbujee.

 public static bool DoRemoteWebServiceWork() { bool result; RemoteWebServiceClient client = new RemoteWebServiceClient(); try { result = client.DoWork(); client.Close(); } catch (Exception) { client.Abort(); //dispose //throw; //This service is auxiliary to the applications primary function. We have no influence over the service and therefore cannot fix it. //could log end point and binding exceptions to avoid ignoring changes to the remote service that require updates to our code. } return result; } 

Definitivamente, sí, es una mala práctica, usar la clase Exception

Debería preocuparse por los tipos de excepción, sin cortar todas las excepciones en el bloque catch, evitando que informen al sistema del error.

La clase de excepción es una clase base, y es una excepción de nivel superior que se puede atrapar en el código. Utilice las Excepciones más específicas en el bloque catch, específicamente, el único que su código genera en un bloque try {…} catch {…}, y solo si puede resolverse efectivamente en ese nivel particular (en un función, donde try … catch block está declarado)

Eso depende de lo que haga si detecta un error. Si solo captas todos los errores para que parezcan manejarlos correctamente, es una mala práctica. Diría que es una mala práctica, incluso si solo inicias sesión allí, registrate localmente.

Si realmente haces algo para recuperar el error (por ejemplo, lo lanzaste tú mismo y sabes qué hacer al respecto), votaría bien 🙂