Estoy casi seguro de que la respuesta es SÍ. Si utilizo un bloque Probar finalmente pero no uso un bloque Catch, entonces aparecerán las excepciones. ¿Correcto?
¿Alguna idea sobre la práctica en general?
Seth
Estoy casi seguro de que la respuesta es SÍ. Si utilizo un bloque Probar finalmente pero no uso un bloque Catch, entonces aparecerán las excepciones. ¿Correcto?
¿Alguna idea sobre la práctica en general?
Seth
Respuestas:
Sí, absolutamente lo hará. Suponiendo que su finally
bloque no arroja una excepción, por supuesto, en cuyo caso eso efectivamente "reemplazará" al que se lanzó originalmente.
¿Alguna idea sobre la práctica en general?
Si. Ten cuidado . Cuando su bloque finalmente se está ejecutando, es muy posible que se esté ejecutando porque se ha lanzado una excepción inesperada no controlada . Eso significa que algo está roto y podría estar sucediendo algo completamente inesperado .
En esa situación, podría decirse que no debería ejecutar código en bloques finalmente. El código en el bloque finalmente podría construirse para asumir que los subsistemas de los que depende están en buen estado, cuando en realidad podrían estar profundamente dañados. El código en el bloque finalmente podría empeorar las cosas.
Por ejemplo, a menudo veo este tipo de cosas:
DisableAccessToTheResource();
try
{
DoSomethingToTheResource();
}
finally
{
EnableAccessToTheResource();
}
El autor de este código está pensando "Estoy haciendo una mutación temporal en el estado del mundo; necesito restaurar el estado a lo que era antes de que me llamaran". Pero pensemos en todas las formas en que esto podría salir mal.
Primero, la persona que llama ya podría deshabilitar el acceso al recurso; en ese caso, este código lo vuelve a habilitar, posiblemente de forma prematura.
En segundo lugar, si DoSomethingToTheResource arroja una excepción, ¿es lo correcto para habilitar el acceso al recurso? El código que administra el recurso se rompe inesperadamente . Este código dice, en efecto, "si el código de administración está roto, asegúrese de que otro código pueda llamar a ese código roto lo antes posible, para que también pueda fallar horriblemente ". Parece una mala idea.
En tercer lugar, si DoSomethingToTheResource genera una excepción, ¿cómo sabemos que EnableAccessToTheResource no generará también una excepción? Independientemente de lo que sucedió con el uso del recurso, también podría afectar el código de limpieza, en cuyo caso la excepción original se perderá y el problema será más difícil de diagnosticar.
Tiendo a escribir código como este sin usar bloques de prueba finalmente:
bool wasDisabled = IsAccessDisabled();
if (!wasDisabled)
DisableAccessToTheResource();
DoSomethingToTheResource();
if (!wasDisabled)
EnableAccessToTheResource();
Ahora el estado no está mutado a menos que sea necesario. Ahora el estado de la persona que llama no está alterado. Y ahora, si DoSomethingToTheResource falla, entonces no volvemos a habilitar el acceso. Asumimos que algo está profundamente roto y no corremos el riesgo de empeorar la situación al intentar seguir ejecutando el código. Deje que la persona que llama se ocupe del problema, si puede.
Entonces, ¿cuándo es una buena idea ejecutar un bloque finalmente? Primero, cuando se espera la excepción. Por ejemplo, puede esperar que un intento de bloquear un archivo falle, porque alguien más lo ha bloqueado. En ese caso, tiene sentido detectar la excepción e informar al usuario. En ese caso se reduce la incertidumbre sobre lo que se rompe; es poco probable que empeore las cosas limpiando.
En segundo lugar, cuando el recurso que está limpiando es un recurso del sistema escaso. Por ejemplo, tiene sentido cerrar un identificador de archivo en un bloque finalmente. (Un "uso" es, por supuesto, solo otra forma de escribir un bloque de intentar finalmente.) El contenido del archivo puede estar dañado, pero no hay nada que pueda hacer al respecto ahora. El identificador de archivo se cerrará eventualmente, por lo que podría ser más temprano que tarde.