Try...Catch...Finally ステートメント (Visual Basic)

コードの実行中に、コードのブロックで発生する可能性のあるエラーの一部またはすべてを処理する方法を提供します。

Try
    [ tryStatements ]
    [ Exit Try ]
[ Catch [ exception [ As type ] ] [ When expression ]
    [ catchStatements ]
    [ Exit Try ] ]
[ Catch ... ]
[ Finally
    [ finallyStatements ] ]
End Try

指定項目

語句

定義

tryStatements

省略可能です。 エラーが発生する可能性のあるステートメント。 複合ステートメントを指定することもできます。

Catch

省略可能です。 複数の Catch ブロックを指定できます。 Try ブロックの処理時に例外が発生した場合は、それぞれの Catch ステートメントがテキストの順序で評価され、その例外を処理できるかどうかが調べられます。このとき、スローされた例外は exception で表されます。

exception

省略可能です。 任意の変数名を指定します。 exception の初期値は、スローされたエラーの値です。 Catch と共に使用して、キャッチされたエラーを指定します。 省略した場合、Catch ステートメントはどの例外でもキャッチします。

type

省略可能です。 クラス フィルターの種類を指定します。 exception の値が type で指定した型、または派生した型の値と一致する場合は、その識別子が例外オブジェクトにバインドされます。

When

省略可能です。 Catch ステートメントに When 句が記述されている場合は、expression の評価が True になるときにのみ例外がキャッチされます。 When 句は、例外の型をチェックした後にだけ適用されます。expression は、例外を表す識別子を参照することがあります。

expression

省略可能です。 暗黙的にブール型 (Boolean) に変換できる必要があります。 汎用フィルターを記述する任意の式。 通常、エラー番号によるフィルター処理に使用されます。 When キーワードと共に使用して、エラーがキャッチされる状況を指定します。

catchStatements

省略可能です。 関連付けられた Try ブロックで発生したエラーを処理するステートメントです。 複合ステートメントを指定することもできます。

Exit Try

省略可能です。 Try...Catch...Finally 構造から抜けるためのキーワードです。 End Try ステートメントのすぐ下にあるコードから実行が再開されます。 その場合でも、Finally ステートメントは実行されます。 Finally ブロック内には記述できません。

Finally

省略可能です。 Try...Catch ステートメントから抜けるときには、必ず Finally ブロックが実行されます。

finallyStatements

省略可能です。 他のエラー処理がすべて行われた後に実行されるステートメント。

End Try

Try...Catch...Finally 構造の終わりを表します。

解説

コード内の特定のセクションで特定の例外が発生することが予想される場合、コードを Try ブロック内に記述し、Catch ブロックを使用してコントロールを保持して、例外が発生した場合にこれを処理するようにします。

Try…Catch ステートメントは、Try ブロックと、それに続く 1 つ以上の Catch 句で構成されます。この句にはさまざまな例外のハンドラーを指定します。 Try ブロックで例外がスローされると、Visual Basic は、その例外を処理する Catch ステートメントを検索します。 対応する Catch ステートメントが見つからない場合、Visual Basic は現在のメソッドの呼び出し元メソッドをチェックします (この方法で、呼び出しスタックの上位をチェックしていきます)。 Catch ブロックが見つからない場合、Visual Basic は未処理例外のメッセージをユーザーに表示し、プログラムの実行を停止します。

Try…Catch ステートメントでは、複数の Catch ステートメントを使用できます。 この場合、Catch 句は順序どおりにチェックされるため、その順序が重要になります。 例外は、特定性の高い順にキャッチしてください。

次のような Catch ステートメントの条件は、特定性が最も低く、Exception クラスから派生するすべての例外がキャッチされます。 通常は、Try...Catch...Finally 構造内で、期待する特定の例外すべてをキャッチした後の最後の Catch ブロックとして、これらのバリエーションのいずれかを使用する必要があります。 制御フローは、これらのバリエーションのいずれかより後の Catch ブロックに到達できません。

  • type が Exception である (例: Catch ex As Exception)。

  • ステートメントに exception 変数がない (例: Catch)。

Try…Catch…Finally ステートメントが別の Try ブロック内に入れ子になっている場合、Visual Basic は、最初に最も内側の Try ブロック内の各 Catch ステートメントをチェックします。 対応する Catch ステートメントが見つからなかった場合は、外側にある Try…Catch…Finally ブロックの Catch ステートメントが検索されます。

Try ブロックと Catch ブロックは別々のブロックであるため、Try ブロック内のローカル変数を Catch ブロック内で使用することはできません。 変数を複数のブロックで使用するには、その変数を Try...Catch...Finally 構造の外で宣言します。

ヒント

Try…Catch…Finally ステートメントは、IntelliSense コード スニペットとして利用できます。 コード スニペット マネージャーで、[コード パターン - If、For Each、Try Catch、Property、その他][エラー処理 (例外)] の順に展開します。 詳細については、「方法 : IntelliSense コード スニペットを挿入する」を参照してください。

Finally ブロック

Try 構造体を終了する前に実行するステートメントがある場合は、Finally ブロックを使用します。 コントロールは Try…Catch 構造体に移る直前に Finally ブロックに移ります。 これは、Try 構造体の中で例外が発生した場合でも同様です。

Finally ブロックは、例外が発生した場合でも実行する必要があるコードを実行するのに便利です。 制御は、Try...Catch ブロックがどのように終了したかに関係なく、Finally ブロックに移動します。

Finally ブロック内のコードは、コードで Try ブロックまたは Catch ブロック内に Return ステートメントがある場合でも実行されます。 次の場合、コントロールは Try または Catch ブロックから、対応する Finally ブロックに移りません。

Finally ブロックに実行を明示的に転送することは無効です。 また、例外の場合を除いて、Finally ブロックの外に実行を転送することも無効です。

Try ステートメント内に Catch ブロックが 1 つもない場合は、Finally ブロックを含める必要があります。

ヒント

特定の例外をキャッチする必要がない場合には、Using ステートメントを使用すると Try…Finally ブロックと同じように動作し、どのようにブロック内の処理が終了する場合でも確実にリソースを解放できます。 これは、未処理の例外の場合にも該当します。 詳細については、「Using ステートメント (Visual Basic)」を参照してください。

例外の引数

Catch ブロックの exception 引数は、Exception クラスのインスタンス、または Exception クラスから派生したクラスのインスタンスです。 Exception クラス インスタンスは、Try ブロックで発生したエラーに対応します。

Exception オブジェクトのプロパティは、例外の原因と場所を特定するのに役立ちます。 たとえば、StackTrace プロパティでは、例外が発生するまでに呼び出されたメソッドの一覧を確認できるため、コードのどこでエラーが発生したのかを突き止めるのに便利です。 Message は、例外を説明するメッセージを返します。 HelpLink は、関連付けられたヘルプ ファイルへのリンクを返します。 InnerException は、現在の例外の原因になった Exception オブジェクトを返します。元の Exception がない場合は、Nothing を返します。

Try…Catch ステートメントを使用する場合の考慮事項

Try…Catch ステートメントは、異常なプログラム イベントまたは予期しないプログラム イベントの発生を伝えるためだけに使用してください。 これには次のような理由があります。

  • 実行時に例外をキャッチすると、追加のオーバーヘッドが発生し、多くの場合、事前にチェックして例外を回避する場合よりも処理が遅くなります。

  • Catch ブロックが適切に処理されない場合、例外がユーザーに適切に報告されないことがあります。

  • 例外処理によってプログラムがより複雑になります。

発生する可能性が高い条件をチェックするのに、Try…Catch ステートメントが常に必要なわけではありません。 ファイルを開く前にファイルの有無をチェックする例を次に示します。 これにより、OpenText メソッドによってスローされる例外をキャッチする必要性が低くなります。

Private Sub TextFileExample(ByVal filePath As String)

    ' Verify that the file exists.
    If System.IO.File.Exists(filePath) = False Then
        Console.Write("File Not Found: " & filePath)
    Else
        ' Open the text file and display its contents.
        Dim sr As System.IO.StreamReader =
            System.IO.File.OpenText(filePath)

        Console.Write(sr.ReadToEnd)

        sr.Close()
    End If
End Sub

Catch ブロック内のコードで、スレッド セーフなログまたは適切なメッセージを通じて、例外がユーザーに適切に報告されるようにしてください。 そうでない場合、例外に気付かないままになる可能性があります。

部分的に信頼されている状況

ネットワーク共有でホストされているアプリケーションなど、部分的に信頼されている状況では、Try...Catch...Finally はその呼び出しを含むメソッドが呼び出される前に発生したセキュリティ例外をキャッチしません。 次のコード例をサーバー共有に配置し、そこから実行すると、"System.Security.SecurityException: 要求が失敗しました。" のエラーが発生します。 セキュリティ例外の詳細については、SecurityException クラスの説明を参照してください。

Try
    Process.Start("https://www.microsoft.com")
Catch ex As Exception
    MsgBox("Can't load Web page" & vbCrLf & ex.Message)
End Try

このような部分的に信頼されている状況では、Process.Start ステートメントを別の Sub に入れる必要があります。 Sub の最初の呼び出しは失敗します。 これによって、Try...Catch は、Process.Start を含んでいる Sub が開始されてセキュリティ例外が生成される前に、その失敗をキャッチできます。

使用例

次の例は、Try...Catch...Finally ステートメントの構造を示しています。

Public Sub TryExample()
    ' Declare variables.
    Dim x As Integer = 5
    Dim y As Integer = 0

    ' Set up structured error handling.
    Try
        ' Cause a "Divide by Zero" exception.
        x = x \ y

        ' This statement does not execute because program
        ' control passes to the Catch block when the
        ' exception occurs.
        MessageBox.Show("end of Try block")
    Catch ex As Exception
        ' Show the exception's message.
        MessageBox.Show(ex.Message)

        ' Show the stack trace, which is a list of methods
        ' that are currently executing.
        MessageBox.Show("Stack Trace: " & vbCrLf & ex.StackTrace)
    Finally
        ' This line executes whether or not the exception occurs.
        MessageBox.Show("in Finally block")
    End Try
End Sub

次の例では、CreateException メソッドにより NullReferenceException がスローされます。 Try ブロックには、例外を生成するコードはありません。 そのため、CreateException メソッドは例外を処理しません。 RunSample メソッドが例外を処理します。これは、CreateException メソッドの呼び出しが Try ブロック内にあるためです。

例には、最も特殊な例外から最も一般的な例外の順に、いくつかの種類の例外のための Catch ステートメントが含まれています。

Public Sub RunSample()
    Try
        CreateException()
    Catch ex As System.IO.IOException
        ' Code that reacts to IOException.
    Catch ex As NullReferenceException
        MessageBox.Show("NullReferenceException: " & ex.Message)
        MessageBox.Show("Stack Trace: " & vbCrLf & ex.StackTrace)
    Catch ex As Exception
        ' Code that reacts to any other exception.
    End Try
End Sub

Private Sub CreateException()
    ' This code throws a NullReferenceException.
    Dim obj = Nothing
    Dim prop = obj.Name

    ' This code also throws a NullReferenceException.
    'Throw New NullReferenceException("Something happened.")
End Sub

次の例は、Catch When ステートメントを使用して、条件式によってフィルターする方法を示しています。 条件式が True と評価された場合に、Catch ブロック内のコードが実行されます。

Private Sub WhenExample()
    Dim i As Integer = 5

    Try
        Throw New ArgumentException()
    Catch e As OverflowException When i = 5
        Console.WriteLine("First handler")
    Catch e As ArgumentException When i = 4
        Console.WriteLine("Second handler")
    Catch When i = 5
        Console.WriteLine("Third handler")
    End Try
End Sub
' Output: Third handler

次の例には、Try ブロックに含まれている Try…Catch ステートメントがあります。 内側の Catch ブロックによって、InnerException プロパティが元の例外に設定されている例外がスローされます。 外側の Catch ブロックによって、それ自体の例外と内側の例外が報告されます。

Private Sub InnerExceptionExample()
    Try
        Try
            ' Set a reference to a StringBuilder.
            ' The exception below does not occur if the commented
            ' statement is used instead.
            Dim sb As System.Text.StringBuilder
            'Dim sb As New System.Text.StringBuilder

            ' Cause a NullReferenceException.
            sb.Append("text")
        Catch ex As Exception
            ' Throw a new exception that has the inner exception
            ' set to the original exception.
            Throw New ApplicationException("Something happened :(", ex)
        End Try
    Catch ex2 As Exception
        ' Show the exception.
        Console.WriteLine("Exception: " & ex2.Message)
        Console.WriteLine(ex2.StackTrace)

        ' Show the inner exception, if one is present.
        If ex2.InnerException IsNot Nothing Then
            Console.WriteLine("Inner Exception: " & ex2.InnerException.Message)
            Console.WriteLine(ex2.StackTrace)
        End If
    End Try
End Sub

参照

参照

Err

Exit ステートメント (Visual Basic)

On Error ステートメント (Visual Basic)

Exception

Throw ステートメント (Visual Basic)

概念

IntelliSense コード スニペットの最適な使用方法

その他の技術情報

例外処理 (タスク並列ライブラリ)

Visual Basic での構造化例外処理

履歴の変更

日付

履歴

理由

2011 年 4 月

解説が再構成および追加され、例が追加されました。

情報の拡充