try technical practices handling exceptions ejemplo custom catch best c# exception-handling

c# - technical - ¿Hay alguna razón técnica para escribir un bloque catch que contenga solo una declaración de lanzamiento?



throw exception c# (3)

Afecta cuando se ejecutan los filtros de excepción.

Dado

void f() { using (var x = AcquireResource()) { x.DoSomething(); x.DoSomethingElse(); } }

versus

void f() { try { using (var x = AcquireResource()) { x.DoSomething(); x.DoSomethingElse(); } } catch { throw; } }

con

void g() { try { f(); } catch (Exception ex) when (h()) { // ... } }

La primera versión de f permitiría llamar al filtro h() antes de que se eliminara x . La segunda versión de f garantiza que x se elimine antes de ejecutar el código externo.

En el código al que se vincula, SqlConnectionHolder se usa mucho y catch { throw; } catch { throw; } bloques están relacionados con el uso de SqlConnectionHolder .

Descargo de responsabilidad: es bien sabido que catch (ex) { throw ex; } catch (ex) { throw ex; } es una mala práctica . Esta pregunta no es sobre eso.

Mientras buscaba en las fuentes de referencia de Microsoft, noté el siguiente patrón en muchos métodos :

try { ... } catch { throw; }

Sin registro, sin código de depuración, solo un simple y sencillo catch { throw; } catch { throw; } .

Como, obviamente, los tipos de Microsoft deberían ser bastante competentes en el uso de C #, ¿cuál podría ser el punto de hacerlo en lugar de simplemente omitir el bloque catch (y la declaración de prueba) por completo? ¿Existe una razón técnica para la codificación como esta, o es puramente una elección estilística?

Nota : no sé si es relevante, pero todas esas instancias que podría encontrar también contienen un bloque try-finally anidado dentro de la cláusula try-catch bloque try-catch .


Como la especificación de C # describe:

Cuando se produce una excepción, el sistema busca la cláusula catch más cercana que pueda manejar la excepción, según lo determine el tipo de tiempo de ejecución de la excepción. Primero, se busca en el método actual una declaración de try que incluya léxicamente, y las cláusulas catch asociadas de la instrucción de try se consideran en orden. Si eso falla, se busca en el método que llamó al método actual una declaración de try que encierra léxicamente que encierre el punto de la llamada al método actual. Esta búsqueda continúa hasta que se encuentra una cláusula catch que puede manejar la excepción actual, al nombrar una clase de excepción que es de la misma clase, o una clase base, del tipo de tiempo de ejecución de la excepción que se lanza. Una cláusula catch que no nombra una clase de excepción puede manejar cualquier excepción.

Una vez que se encuentra una cláusula catch coincidente, el sistema se prepara para transferir el control a la primera declaración de la cláusula catch . Antes de que comience la ejecución de la cláusula catch , el sistema primero ejecuta, en orden, las cláusulas finally asociadas con las sentencias de try más anidadas que la que detectó la excepción.

en caso de excepción, el tiempo de ejecución busca primero una cláusula catch que pueda manejarla, lo que implica la ejecución de cualquier filtro de excepción asociado. El bloque catch indiscriminado interrumpe la búsqueda y hace que todos los bloques anidados finally se ejecuten inmediatamente.

Eso puede ser útil cuando quiere evitar que la persona que llama ejecute un código arbitrario (en forma de filtro de excepción) antes de que finally bloquee. Por ejemplo, cuando finally bloque afecta el contexto de seguridad del hilo actual.

Además, si una cláusula catch no captura la excepción, se producirá la terminación del hilo. Y en ese caso, la especificación C # no proporcionó ninguna garantía, de que cualquier bloque final se ejecutará en absoluto.

Si la búsqueda de cláusulas catch coincidentes alcanza el código que inicialmente inició el subproceso, se termina la ejecución del subproceso. El impacto de dicha terminación está definido por la implementación.


El código que has vinculado es en realidad un muy buen ejemplo.

En mi opinión, uno solo debería usar los bloques try catch cuando se trata de cosas fuera de su control, como sistemas de archivos, básicamente cosas externas.

En el código que vinculaste, la captura de prueba está alrededor de la base de datos.

Lo que esto significa es que al usar esta forma de codificación, se aseguran de que no haya fugas, que no haya conexiones abiertas.

Si algo sale mal, como una cadena de conexión incorrecta, tablas faltantes, lo que sea, el código continuará ejecutándose, cerrará con gracia la conexión como se muestra en el bloque finally y finalmente lanzará el significado que permitirá al cliente de ese código para obtener la excepción adecuada, obtenga la pila completa también y deje que ellos decidan qué hacer cuando eso suceda.

Para ser honesto, me gusta bastante lo que hicieron allí.