¿Es una mala práctica regresar desde dentro de un intento de captura finalmente bloquear?

128

Así que encontré un código esta mañana que se veía así:

try
{
    x = SomeThingDangerous();
    return x;
}
catch (Exception ex)
{
    throw new DangerousException(ex);
}
finally
{
    CleanUpDangerousStuff();
}

Ahora este código se compila bien y funciona como debería, pero no parece correcto regresar desde un bloque de prueba, especialmente si finalmente hay un asociado.

Mi principal problema es ¿qué sucede si finalmente arroja una excepción propia? Tienes una variable devuelta pero también una excepción con la que lidiar ... así que me interesa saber qué piensan los demás acerca de regresar desde un bloque de prueba.

lomaxx
fuente
13
Una ventaja de este estilo es que no tiene que declarar xfuera del trybloque. Puede mantener su declaración cerca de su uso.
David R Tribble

Respuestas:

169

No, no es una mala práctica. Poner returnlo que tiene sentido mejora la legibilidad y la facilidad de mantenimiento y hace que su código sea más fácil de entender. No debería importarle que el finallybloque se ejecutará si returnse encuentra una instrucción.

Mehrdad Afshari
fuente
19

El finalmente se ejecutará sin importar qué, así que no importa.

Ed S.
fuente
9
No, de hecho, no se trata solo de enchufar, hay algunas excepciones llamadas excepciones asincrónicas como StackOverflowException, ThreadAbortException y OutOfMemoryException que pueden hacer que el bloque finalmente no se ejecute. Lea sobre las regiones de ejecución restringidas para manejar estos escenarios.
Mehrdad Afshari
14

Personalmente, evitaría este tipo de codificación ya que no tengo ganas de ver las declaraciones de retorno antes de las declaraciones finales.

Mi mente es simple y procesa las cosas de forma bastante lineal. Por lo tanto, cuando revise el código para el funcionamiento en seco, tendré la tendencia a pensar que una vez que pueda alcanzar la declaración de devolución, todo lo que sigue no importa, lo que obviamente es bastante incorrecto en este caso (no es que afecte la declaración de devolución, pero cuáles podrían ser los efectos secundarios).

Por lo tanto, organizaría el código para que la declaración de devolución siempre aparezca después de las declaraciones finalmente.

Conrad
fuente
9

Esto puede responder tu pregunta

Lo que realmente sucede en un intento {return x; } finalmente {x = nulo; } declaración?

Al leer esa pregunta, parece que puede tener otra estructura de captura de prueba en la declaración final si cree que podría arrojar una excepción. El compilador determinará cuándo devolver el valor.

Dicho esto, podría ser mejor reestructurar su código de todos modos solo para que no lo confunda más adelante ni a otra persona que también no se dé cuenta de esto.

Spencer Ruport
fuente
hmmm muy interesante. Eso significa que es seguro, pero ¿eso significa que debería evitarse?
lomaxx
3
Personalmente, creo que dificulta un poco la legibilidad de su código y eso solo sería suficiente para hacerme descubrir otra forma de estructurar el código. Pero en realidad es solo una preferencia personal.
Spencer Ruport
3
Tiendo
Creo que el retorno está bien donde está. El método devolverá el valor, a menos que se produzca una excepción; no importa si surge la excepción en el código de limpieza final.
Lawrence Dol el
Tenga en cuenta que la restricción para regresar finalmente no está presente en Java (pero creo que la restricción es buena, felicitaciones a C #).
Lawrence Dol
5

Funcionalmente no hay diferencia.

Sin embargo, hay una razón para no hacer esto. Los métodos más largos con varios puntos de salida suelen ser más difíciles de leer y analizar. Pero esa objeción tiene más que ver con las declaraciones de retorno que catch y finalmente bloquea.

Ifeanyi Echeruo
fuente
Desafiaría esto, ya que podría terminar con más anidamiento que también hace que sea más difícil leer una mayor complejidad ciclomática
matt_lethargic
3

En su ejemplo, de cualquier manera es equivalente, ni siquiera me sorprendería si el compilador generara el mismo código. Si ocurre una excepción en el bloque finalmente, tiene los mismos problemas si pone la declaración de devolución en bloque o fuera de ella.

La verdadera pregunta es estilísticamente cuál es la mejor. Me gusta escribir mis métodos para que solo haya una declaración de retorno, de esta manera es más fácil ver el flujo del método, se deduce que también me gusta poner la declaración de retorno al final para que sea fácil ver que es Al final del método y esto es lo que devuelve.

Creo que con la declaración de devolución colocada tan prolijamente como la última declaración, es menos probable que otros vengan y esparzan múltiples declaraciones de devolución en otras partes del método.

Advertencia
fuente