异常:try...finally 表达式
你可以通过 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 表达式可以具有自定义实现。 有关详细信息,请参阅计算表达式。