例外: try...finally 式
try...finally
式を使用すると、コードのブロックで例外がスローされた場合でもクリーンアップ コードを実行できます。
構文
try
expression1
finally
expression2
解説
try...finally
式を使用すると、上記の構文で expression1 の実行中に例外が生成されたかどうかに関係なく、expression2 のコードを実行することができます。
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
ブロックの両方が必要な場合は、次のコード例に示すように、2 つのコンストラクトを入れ子にする必要があります。
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 式にカスタム実装を含めることができます。 詳細については、「コンピュテーション式」をご覧ください。
関連項目
.NET