例外: try...with 式

このトピックでは、F# 言語での例外処理に使用される式である try...with 式について説明します。

構文

try
    expression1
with
| pattern1 -> expression2
| pattern2 -> expression3
...

解説

try...with 式は、F# で例外を処理するために使用されます。 これは、C# の try...catch ステートメントに似ています。 前の構文で、expression1 のコードによって例外が生成されるとします。 try...with 式によって値が返されます。 例外がスローされない場合、式全体によって expression1 の値が返されます。 例外がスローされた場合、各 "パターン" がその例外と比較され、最初の一致パターンで、そのブランチに対応する "" ("例外ハンドラー" と呼ばれる) が実行され、式全体により、その例外ハンドラーの式の値が返されます。 一致するパターンがない場合、例外は、一致するハンドラーが見つかるまで呼び出し履歴をさかのぼります。 例外ハンドラー内の各式から返される値の型は、try ブロック内の式から返される型と一致する必要があります。

多くの場合、エラーが発生したということは、各例外ハンドラーの式から返される有効な値がないことも示します。 一般的なパターンは、式の型がオプション型になるというものです。 このパターンを次のコード例に示します。

let divide1 x y =
   try
      Some (x / y)
   with
      | :? System.DivideByZeroException -> printfn "Division by zero!"; None

let result1 = divide1 100 0

例外は .NET 例外とすることも、F# 例外とすることもできます。 exception キーワードを使用して、F# 例外を定義できます。

さまざまなパターンを使用して、例外の種類やその他の条件を基にフィルター処理が行えます。次の表に、オプションの概要を示します。

パターン 説明
:? exception-type 指定された .NET 例外の種類と一致します。
:? exception-type as identifier 指定された .NET 例外の種類と一致しますが、例外に名前付きの値を指定します。
exception-name(arguments) F# 例外の種類と一致し、引数をバインドします。
identifier 任意の例外と一致し、その名前を例外オブジェクトにバインドします。 :?System.Exception asidentifier と同じです
identifier when condition 条件が true の場合、すべての例外と一致します。

次のコード例は、さまざまな例外ハンドラー パターンの使用方法を示しています。

// This example shows the use of the as keyword to assign a name to a
// .NET exception.
let divide2 x y =
  try
    Some( x / y )
  with
    | :? System.DivideByZeroException as ex -> printfn "Exception! %s " (ex.Message); None

// This version shows the use of a condition to branch to multiple paths
// with the same exception.
let divide3 x y flag =
  try
     x / y
  with
     | ex when flag -> printfn "TRUE: %s" (ex.ToString()); 0
     | ex when not flag -> printfn "FALSE: %s" (ex.ToString()); 1

let result2 = divide3 100 0 true

// This version shows the use of F# exceptions.
exception Error1 of string
exception Error2 of string * int

let function1 x y =
   try
      if x = y then raise (Error1("x"))
      else raise (Error2("x", 10))
   with
      | Error1(str) -> printfn "Error1 %s" str
      | Error2(str, i) -> printfn "Error2 %s %d" str i

function1 10 10
function1 9 2

注意

try...with コンストラクトは、try...finally 式とは別の式です。 したがって、コードに with ブロックと finally ブロックの両方が必要な場合は、2 つの式を入れ子にする必要があります。

注意

try...with は、非同期ワークフローやその他のコンピュテーション式で使用することができます。その場合は、try...with 式のカスタマイズされたバージョンを使用します。 詳細については、「非同期ワークフロー」、「コンピュテーション式」を参照してください。

関連項目