utilizar try tipos que para net manejo manejar existen excepciones errores ejemplos como catch capturar asp c# .net exception-handling

try - manejo de excepciones en asp net c#



¿Cuál es la forma correcta de volver a lanzar una excepción en C#? (9)

Depende. En una compilación de depuración, quiero ver el seguimiento de la pila original con el menor esfuerzo posible. En ese caso, "tirar"; encaja a la perfección. Sin embargo, en una versión de lanzamiento, (a) quiero registrar el error con el seguimiento de pila original incluido, y una vez hecho esto, (b) remodelar el manejo de errores para que tenga más sentido para el usuario. Aquí "Lanzar Excepción" tiene sentido. Es cierto que volver a generar el error descarta el seguimiento de la pila original, pero un desarrollador no obtiene nada al ver la información de seguimiento de la pila, por lo que está bien volver a emitir el error.

void TrySuspectMethod() { try { SuspectMethod(); } #if DEBUG catch { //Don''t log error, let developer see //original stack trace easily throw; #else catch (Exception ex) { //Log error for developers and then //throw a error with a user-oriented message throw new Exception(String.Format ("Dear user, sorry but: {0}", ex.Message)); #endif } }

La forma en que está redactada la pregunta, que enfrenta a "Throw:" frente a "Throw ex;" hace que sea un poco de arenque rojo. La elección real es entre "tirar"; y "Lanzar excepción", donde "Lanzar ex"; Es un caso especial poco probable de "Excepción de tiro".

Esta pregunta ya tiene una respuesta aquí:

Tengo una pregunta para usted que proviene de que mi pareja hace las cosas de una manera diferente a la que yo hago.

¿Es mejor hacer esto?

try { ... } catch (Exception ex) { ... throw; }

o esto:

try { ... } catch (Exception ex) { ... throw ex; }

¿Hacen lo mismo? ¿Es uno mejor que el otro?


Descubrí que si la excepción se produce en el mismo método que se captura, el seguimiento de pila no se conserva, por lo que vale.

void testExceptionHandling() { try { throw new ArithmeticException("illegal expression"); } catch (Exception ex) { throw; } finally { System.Diagnostics.Debug.WriteLine("finally called."); } }


El primero conserva el rastro de pila original de la excepción, el segundo lo reemplaza con la ubicación actual.

Por lo tanto, el primero es, por mucho, mejor.


El primero es mejor. Si intenta depurar el segundo y mira la pila de llamadas, no verá de dónde proviene la excepción original. Hay trucos para mantener intacta la pila de llamadas (intente buscar, se ha respondido antes) si realmente necesita volver a lanzar.


Mis preferencias es usar

try { } catch (Exception ex) { ... throw new Exception ("Put more context here", ex) }

Esto conserva el error original, pero le permite poner más contexto, como un ID de objeto, una cadena de conexión, cosas así. A menudo, mi herramienta de informes de excepciones tendrá 5 excepciones encadenadas al informe, cada una con más detalles.


Sé que esta es una pregunta antigua, pero voy a responderla porque tengo que estar en desacuerdo con todas las respuestas aquí.

Ahora, estoy de acuerdo en que la mayoría de las veces desea hacer una throw simple, para preservar la mayor cantidad de información posible acerca de lo que salió mal, o quiere lanzar una nueva excepción que pueda contener eso como una excepción interna, o no, según la probabilidad de que quiera saber sobre los eventos internos que lo causaron.

Aunque hay una excepción. Hay varios casos en los que un método llamará a otro método y una condición que causa una excepción en la llamada interna debe considerarse la misma excepción en la llamada externa.

Un ejemplo es una colección especializada implementada usando otra colección. Digamos que es una List<T> DistinctList<T> que envuelve una List<T> pero rechaza los elementos duplicados.

Si alguien llamó a ICollection<T>.CopyTo en su clase de colección, podría ser simplemente una llamada directa a CopyTo en la colección interna (por ejemplo, toda la lógica personalizada solo se aplicó para agregar a la colección o configurarla). Ahora, las condiciones en las que se ICollection<T>.CopyTo esa llamada son exactamente las mismas condiciones en las que su colección debería coincidir con la documentación de ICollection<T>.CopyTo .

Ahora, simplemente no podría captar la exención en absoluto, y dejarla pasar. Sin embargo, aquí el usuario obtiene una excepción de la List<T> cuando estaba llamando a algo en una DistinctList<T> . No es el fin del mundo, pero es posible que desee ocultar los detalles de la implementación.

O usted podría hacer su propia comprobación:

public CopyTo(T[] array, int arrayIndex) { if(array == null) throw new ArgumentNullException("array"); if(arrayIndex < 0) throw new ArgumentOutOfRangeException("arrayIndex", "Array Index must be zero or greater."); if(Count > array.Length + arrayIndex) throw new ArgumentException("Not enough room in array to copy elements starting at index given."); _innerList.CopyTo(array, arrayIndex); }

Ese no es el peor código porque está escrito y es probable que podamos copiarlo desde alguna otra implementación de CopyTo donde no fuera un simple paso y tuvimos que implementarlo nosotros mismos. Sin embargo, está repitiendo innecesariamente las mismas comprobaciones que se realizarán en _innerList.CopyTo(array, arrayIndex) , por lo que lo único que ha agregado a nuestro código es 6 líneas donde podría haber un error.

Podríamos revisar y envolver:

public CopyTo(T[] array, int arrayIndex) { try { _innerList.CopyTo(array, arrayIndex); } catch(ArgumentNullException ane) { throw new ArgumentNullException("array", ane); } catch(ArgumentOutOfRangeException aore) { throw new ArgumentOutOfRangeException("Array Index must be zero or greater.", aore); } catch(ArgumentException ae) { throw new ArgumentException("Not enough room in array to copy elements starting at index given.", ae); } }

En términos de nuevo código agregado que podría tener errores, esto es aún peor. Y no ganamos nada de las excepciones internas. Si pasamos una matriz nula a este método y recibimos una ArgumentNullException , no vamos a aprender nada examinando la excepción interna y _innerList.CopyTo que una llamada a _innerList.CopyTo recibió una matriz nula y lanzó una ArgumentNullException .

Aquí, podemos hacer todo lo que queramos con:

public CopyTo(T[] array, int arrayIndex) { try { _innerList.CopyTo(array, arrayIndex); } catch(ArgumentException ae) { throw ae; } }

Cada una de las excepciones que esperamos tener que lanzar si el usuario lo llama con argumentos incorrectos, será lanzada correctamente por ese relanzamiento. Si hay un error en la lógica que se usa aquí, está en una de dos líneas: o bien nos equivocamos al decidir que este fue un caso en el que funciona este enfoque, o nos equivocamos al tener la excepción ArgumentException como el tipo de excepción buscado. Son los dos únicos errores que el bloque catch puede tener.

Ahora. Todavía estoy de acuerdo en que la mayoría de las veces, o bien quieres un throw; sencillo throw; o quiere construir su propia excepción para que coincida más directamente con el problema desde la perspectiva del método en cuestión. Hay casos como el anterior, donde volver a lanzar de esta manera tiene más sentido, y hay muchos otros casos. Por ejemplo, para tomar un ejemplo muy diferente, si un lector de archivos ATOM implementado con un FileStream y un XmlTextReader recibe un error de archivo o un XML no válido, tal vez querrá lanzar exactamente la misma excepción que recibió de esas clases, pero debería tener en cuenta la persona que llama que es AtomFileReader está lanzando una FileNotFoundException o XmlException , por lo que podrían ser candidatos para relanzar de manera similar.

Editar:

También podemos combinar los dos:

public CopyTo(T[] array, int arrayIndex) { try { _innerList.CopyTo(array, arrayIndex); } catch(ArgumentException ae) { throw ae; } catch(Exception ex) { //we weren''t expecting this, there must be a bug in our code that put //us into an invalid state, and subsequently let this exception happen. LogException(ex); throw; } }


Si lanza una excepción sin una variable (el segundo ejemplo), StackTrace incluirá el método original que lanzó la excepción.

En el primer ejemplo, el StackTrace se cambiará para reflejar el método actual.

Ejemplo:

static string ReadAFile(string fileName) { string result = string.Empty; try { result = File.ReadAllLines(fileName); } catch(Exception ex) { throw ex; // This will show ReadAFile in the StackTrace throw; // This will show ReadAllLines in the StackTrace }


Siempre debe usar la siguiente sintaxis para volver a generar una excepción; de lo contrario, pisará el seguimiento de pila:

throw;

Si imprime la traza resultante de "throw ex", verá que termina en esa declaración y no en la fuente real de la excepción.

Básicamente, debe considerarse un delito penal usar "lanzar ex".


Siempre debes usar "lanzar"; para volver a lanzar las excepciones en .NET,

Consulte esto, http://weblogs.asp.net/bhouse/archive/2004/11/30/272297.aspx

Básicamente, MSIL (CIL) tiene dos instrucciones: "lanzar" y "volver a lanzar" y "lanzar ex" de C #; se compila en el "lanzamiento" de MSIL y en el "lanzamiento" de C #; - en MSIL "rethrow"! Básicamente puedo ver la razón por la que "throw ex" reemplaza el seguimiento de la pila.