例外:try...finally 式Exceptions: The try...finally Expression

try...finally式を使用すると、コードのブロックで例外がスローされた場合でもクリーンアップコードを実行できます。The try...finally expression enables you to execute clean-up code even if a block of code throws an exception.

構文Syntax

try
    expression1
finally
    expression2

RemarksRemarks

式は、 expression1の実行中に例外が生成されたかどうかに関係なく、前の構文で expression2 のコードを実行するために使用できます。 try...finallyThe try...finally expression can be used to execute the code in expression2 in the preceding syntax regardless of whether an exception is generated during the execution of expression1.

Expression2の型は、式全体の値には影響しません。例外が発生しないときに返される型は、 expression1の最後の値です。The type of expression2 does not contribute to the value of the whole expression; the type returned when an exception does not occur is the last value in expression1. 例外が発生した場合、値は返されず、制御のフローは、コールスタックの上位にある次の一致する例外ハンドラーに転送されます。When an exception does occur, no value is returned and the flow of control transfers to the next matching exception handler up the call stack. 例外ハンドラーが見つからない場合、プログラムは終了します。If no exception handler is found, the program terminates. 一致するハンドラー内のコードが実行されるか、プログラムが終了する前にfinally 、分岐内のコードが実行されます。Before the code in a matching handler is executed or the program terminates, the code in the finally branch is executed.

次のコードは、 try...finally式の使用方法を示しています。The following code demonstrates the use of the try...finally expression.

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

コンソールへの出力は次のとおりです。The output to the console is as follows.

Closing stream
Exception handled.

出力からわかるように、外側の例外が処理される前にストリームが閉じられていtest.txtます。またtest1、ファイルには、例外が転送されたにもかかわらず、バッファーがフラッシュされ、ディスクに書き込まれたことを示すテキストが含まれています。外側の例外ハンドラーに制御します。As you can see from the output, the stream was closed before the outer exception was handled, and the file test.txt contains the text test1, which indicates that the buffers were flushed and written to disk even though the exception transferred control to the outer exception handler.

コンストラクトは、 try...with try...finallyコンストラクトとは別のコンストラクトであることに注意してください。Note that the try...with construct is a separate construct from the try...finally construct. したがって、コードにwithブロックfinallyとブロックの両方が必要な場合は、次のコード例に示すように、2つの構造体を入れ子にする必要があります。Therefore, if your code requires both a with block and a finally block, you have to nest the two constructs, as in the following code example.

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

シーケンス式と非同期ワークフローを含むコンピュテーション式のコンテキストでは、.. .最後の式には、カスタム実装を含めることができます。In the context of computation expressions, including sequence expressions and asynchronous workflows, try...finally expressions can have a custom implementation. 詳細については、「コンピュテーション式」を参照してください。For more information, see Computation Expressions.

関連項目See also