异常:try...finally 表达式 (F#)

通过使用 try...finally 表达式,即使在代码块引发异常时,也可以执行清理代码。

try
   expression1
finally
   expression2

备注

在上面的语法中,可以使用 try...finally 表达式来执行 expression2 中的代码,而不管在执行 expression1 的过程中是否生成了异常。

expression2 的类型不会影响整个表达式的值;如果没有发生异常,则返回的类型是 expression1 中的最后一个值。 如果发生异常,则不会返回任何值,并且控制流将在调用堆栈中向上转交给下一个匹配的异常处理程序。 如果未找到匹配的异常处理程序,则程序将终止。 在执行匹配的处理程序中的代码或终止程序之前,将执行 finally 分支中的代码。

下面的代码演示了 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

控制台中的输出如下所示。

Closing stream
Exception handled.

从输出中可以看到,在外部异常得到处理之前关闭了流,并且 test.txt 文件包含文本 test1,这表明缓冲区已经过刷新并已写入到磁盘(即使异常已将控制权移交给外部的异常处理程序)。

请注意,try...with 构造独立于 try...finally 构造。 因此,如果您的代码同时需要 with 块和 finally 块,则必须嵌套这两个构造,如以下代码示例中所示。

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

在计算表达式(包括序列表达式和异步工作流)的上下文中,try...finally 表达式可具有自定义实现。 有关更多信息,请参见计算表达式 (F#)

请参见

参考

异常:try...with 表达式 (F#)

其他资源

异常处理 (F#)