Excepciones: expresión try...finally

La expresión try...finally le permite ejecutar código de limpieza aunque un bloque de código produzca una excepción.

Sintaxis

try
    expression1
finally
    expression2

Comentarios

La expresión try...finally se puede usar para ejecutar el código en expression2 en la sintaxis anterior, al margen de si se genera una excepción durante la ejecución de expression1.

El tipo de expression2 no contribuye al valor de toda la expresión; el tipo devuelto cuando no se produce una excepción es el último valor de expression1. Cuando se produce una excepción, no se devuelve ningún valor y el flujo de control se transfiere al siguiente controlador de excepciones coincidente en la pila de llamadas. Si no se encuentra ningún controlador de excepciones, el programa finaliza. Antes de que se ejecute el código de un controlador coincidente o de que finalice el programa, se ejecuta el código de la rama finally.

En el código siguiente se muestra el uso de la expresión try...finally.

let divide x y =
   let stream : System.IO.FileStream = System.IO.File.Create("test.txt")
   let writer : System.IO.StreamWriter = new System.IO.StreamWriter(stream)
   try
      writer.WriteLine("test1")
      Some( x / y )
   finally
      writer.Flush()
      printfn "Closing stream"
      stream.Close()

let result =
  try
     divide 100 0
  with
     | :? System.DivideByZeroException -> printfn "Exception handled."; None

La salida a la consola es la siguiente.

Closing stream
Exception handled.

Como puede ver en la salida, la secuencia se cerró antes de que se controlara la excepción externa y el archivo test.txt contiene el texto test1, lo que indica que los búferes se vaciaron y se escribieron en el disco, aunque la excepción transfiriera el control al controlador de excepciones externo.

Tenga en cuenta que la construcción try...with es independiente de la construcción try...finally. Por lo tanto, si el código requiere un bloque with y un bloque finally, debe anidar las dos construcciones, como en el ejemplo de código siguiente.

exception InnerError of string
exception OuterError of string

let function1 x y =
   try
     try
        if x = y then raise (InnerError("inner"))
        else raise (OuterError("outer"))
     with
      | InnerError(str) -> printfn "Error1 %s" str
   finally
      printfn "Always print this."


let function2 x y =
  try
     function1 x y
  with
     | OuterError(str) -> printfn "Error2 %s" str

function2 100 100
function2 100 10

En el contexto de las expresiones de cálculo, incluidas las expresiones de secuencia y las expresiones asincrónicas, las expresiones try...finally pueden tener una implementación personalizada. Para más información, consulte Expresiones de cálculo.

Consulte también