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 |
任意。 When 句を含む Catch ステートメントは、expression が True に評価される場合にのみ例外をキャッチします。 When 句は、例外の型をチェックした後にのみ適用され、expression は例外を表す識別子を参照する場合があります。 |
expression |
任意。 暗黙的に Boolean に変換される必要があります。 汎用フィルターを記述する任意の式。 通常、エラー番号でフィルター処理するために使用されます。 When キーワードと共に使用して、エラーがキャッチされる状況を指定します。 |
catchStatements |
任意。 関連付けられた Try ブロックで発生するエラーを処理するステートメント。 複合ステートメントにすることもできます。 |
Exit Try |
任意。 Try...Catch...Finally 構造体から抜け出すキーワード。 実行は、End Try ステートメントの直後のコードで再開されます。 Finally ステートメントは引き続き実行されます。 Finally ブロックでは許可されていません。 |
Finally |
任意。 Finally ブロックは、実行が Try...Catch ステートメントの任意の部分から離れたときに常に実行されます。 |
finallyStatements |
任意。 他のエラー処理がすべて実行された後で実行されるステートメント。 |
End Try |
Try...Catch...Finally 構造体を終了します。 |
Remarks
特定の例外がコードの特定のセクションで発生することが予想される場合は、コードを Try
ブロックに配置し、Catch
ブロックを使用して制御を維持し、例外が発生した場合は処理します。
Try…Catch
ステートメントは、Try
ブロックと、それに続く 1 つ以上の Catch
句で構成されます。この句にはさまざまな例外のハンドラーを指定します。 Try
ブロックで例外がスローされると、Visual Basic では、この例外を処理する Catch
ステートメントが検索されます。 一致する Catch
ステートメントが見つからない場合、Visual Basic は、現在のメソッドを呼び出したメソッドを調べ、呼び出し履歴を調べていきます。 Catch
ブロックが見つからない場合、Visual Basic は、ハンドルされない例外のメッセージをユーザーに表示し、プログラムの実行を停止します。
Try…Catch
ステートメント内で複数の Catch
ステートメントを使用できます。 これを実行すると、Catch
句は順序どおりにチェックされるため、順序が重要になります。 例外は、特殊性の高い順に Catch してください。
次の Catch
ステートメントの条件は最も限定的ではなく、Exception クラスから派生したすべての例外を catch します。 通常は、予期したすべての具体的な例外をキャッチした後、これらのバリエーションのいずれかを 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...Finally
構造体の外側で変数を宣言します。
ヒント
Try…Catch…Finally
ステートメントは、IntelliSense コード スニペットとして利用できます。 コード スニペット マネージャーで、[コード パターン - If、For Each、TryCatch、Property、その他] を展開してから、[エラー処理 (例外)] を展開します。 詳細については、「Code Snippets」を参照してください。
Finally ブロック
Try
構造体を終了する前に実行する必要のあるステートメントが 1 つ以上ある場合は、Finally
ブロックを使用します。 制御は、Try…Catch
構造体から渡される直前に Finally
ブロックに渡されます。 これは、Try
構造体の内部のどこかで例外が発生した場合でも当てはまります。
Finally
ブロックは、例外が発生した場合でも実行する必要があるコードを実行する場合に便利です。 制御は、Try...Catch
ブロックの終了方法に関係なく、Finally
ブロックに渡されます。
Finally
ブロック内のコードは、コードが Try
または Catch
ブロックで Return
ステートメントを検出した場合でも実行されます。 次の場合、制御は、Try
または Catch
ブロックから対応する Finally
ブロックに渡されません。
Try
またはCatch
ブロックで End ステートメントが検出された。Try
またはCatch
ブロックで StackOverflowException がスローされた。
実行を明示的に Finally
ブロックに移動することは有効ではありません。 例外を除き、Finally
ブロックからの実行を移動することは有効ではありません。
Try
ステートメントに少なくとも 1 つの Catch
ブロックが含まれていない場合は、Finally
ブロックが含まれている必要があります。
ヒント
特定の例外を catch する必要がない場合、Using
ステートメントは Try…Finally
ブロックのように動作し、ブロックをどのように終了するかに関係なく、リソースの破棄が保証されます。 これは、ハンドルされない例外が発生した場合でも当てはまります。 詳細については、「Using ステートメント」を参照してください。
Exception 引数
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
ブロック内のコードでユーザーに例外を適切に報告できることを確認します。 そうでない場合、例外は不明なままになる可能性があります。
非同期メソッド
メソッドに Async 修飾子を付けると、そのメソッドで Await 演算子を使用できます。 Await
演算子を含むステートメントは、待機しているタスクが完了するまでメソッドの実行を中断します。 このタスクは、進行中の作業を表します。 Await
演算子に関連付けられているタスクが終了すると、実行は同じメソッド内で再開されます。 詳細については、「非同期プログラムにおける制御フロー」を参照してください。
非同期メソッドによって返されるタスクは、ハンドルされない例外が原因で完了したことを示す違反状態で終了することがあります。 また、タスクは取り消された状態で終了することもあります。その結果、await 式から OperationCanceledException
がスローされます。 どちらの種類の例外も catch するには、タスクに関連付けられた Await
式を Try
ブロック内に配置し、Catch
ブロック内で例外を catch します。 例については、このトピックで後述します。
複数の例外が違反の原因になっているため、タスクが違反状態になることがあります。 たとえば、タスクは Task.WhenAll の呼び出しの結果になることがあります。 このようなタスクを待機した場合、キャッチされた例外は例外の 1 つにすぎず、どの例外がキャッチされるかは予測できません。 例については、このトピックで後述します。
Await
式を Catch
ブロックや Finally
ブロックに記述することはできません。
Iterators
iterator 関数または Get
アクセサーは、コレクションに対するカスタムの反復を実行します。 反復子は、Yield ステートメントを使用して、コレクションの各要素を 1 回に 1 つ返します。 For Each...Next ステートメントを使用して、iterator 関数を呼び出します。
Yield
ステートメントは Try
ブロック内に記述できます。 Yield
ステートメントが含まれている Try
ブロックには、Catch
ブロックと Finally
ブロックを記述することができます。 例については、Try ブロックに関する記事を参照してください。
Yield
ステートメントを Catch
ブロックや Finally
ブロックに記述することはできません。
(iterator 関数の外部の) For Each
本体で例外がスローされた場合、iterator 関数の Catch
ブロックは実行されず、iterator 関数の Finally
ブロックが実行されます。 iterator 関数内の Catch
ブロックでキャッチされるのは、iterator 関数内で発生した例外だけです。
部分信頼の状況
ネットワーク共有でホストされているアプリケーションなど、部分信頼の状況において、Try...Catch...Finally
では、呼び出しが含まれるメソッドが呼び出される前に発生したセキュリティ例外は catch されません。 次の例では、サーバー共有に配置し、そこから実行すると、エラー "System.Security.SecurityException:要求が失敗しました。" が生成されます。セキュリティ例外について詳しくは、SecurityException クラスをご覧ください。
Try
Process.Start("http://www.microsoft.com")
Catch ex As Exception
Console.WriteLine("Can't load Web page" & vbCrLf & ex.Message)
End Try
このような部分信頼では、Process.Start
ステートメントを別の Sub
に配置する必要があります。 Sub
の最初の呼び出しは失敗します。 これにより、Process.Start
を含む Sub
が開始されてセキュリティ例外が生成される前に、Try...Catch
がそれを catch できるようになります。
例
Try...Catch...Finally
の構造
次の例は、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.
Console.WriteLine("end of Try block")
Catch ex As Exception
' Show the exception's message.
Console.WriteLine(ex.Message)
' Show the stack trace, which is a list of methods
' that are currently executing.
Console.WriteLine("Stack Trace: " & vbCrLf & ex.StackTrace)
Finally
' This line executes whether or not the exception occurs.
Console.WriteLine("in Finally block")
End Try
End Sub
Try
ブロックから呼び出されたメソッドでの例外
次の例では、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
Console.WriteLine("NullReferenceException: " & ex.Message)
Console.WriteLine("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 ステートメント
次の例では、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
ブロックに含まれる 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
' out 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
非同期メソッドの例外処理
次の例では、非同期メソッドの例外処理を示します。 非同期タスクに適用される例外を catch するために、Await
式を呼び出し元の Try
ブロックに配置し、例外を Catch
ブロックでキャッチしています。
例外処理を示すために、この例の Throw New Exception
行のコメントを解除します。 例外が Catch
ブロックでキャッチされ、タスクの IsFaulted
プロパティが True
に設定され、タスクの Exception.InnerException
プロパティが例外に設定されます。
Throw New OperationCancelledException
行のコメントを解除して、非同期処理を取り消したときに何が起こるかを示します。 例外が True
ブロックでキャッチされ、タスクの Catch
プロパティが IsCanceled
に設定されます。 ただし、この例に該当しない一部の条件では、IsFaulted
が True
に設定され、IsCanceled
が False
に設定されます。
Public Async Function DoSomethingAsync() As Task
Dim theTask As Task(Of String) = DelayAsync()
Try
Dim result As String = Await theTask
Debug.WriteLine("Result: " & result)
Catch ex As Exception
Debug.WriteLine("Exception Message: " & ex.Message)
End Try
Debug.WriteLine("Task IsCanceled: " & theTask.IsCanceled)
Debug.WriteLine("Task IsFaulted: " & theTask.IsFaulted)
If theTask.Exception IsNot Nothing Then
Debug.WriteLine("Task Exception Message: " &
theTask.Exception.Message)
Debug.WriteLine("Task Inner Exception Message: " &
theTask.Exception.InnerException.Message)
End If
End Function
Private Async Function DelayAsync() As Task(Of String)
Await Task.Delay(100)
' Uncomment each of the following lines to
' demonstrate exception handling.
'Throw New OperationCanceledException("canceled")
'Throw New Exception("Something happened.")
Return "Done"
End Function
' Output when no exception is thrown in the awaited method:
' Result: Done
' Task IsCanceled: False
' Task IsFaulted: False
' Output when an Exception is thrown in the awaited method:
' Exception Message: Something happened.
' Task IsCanceled: False
' Task IsFaulted: True
' Task Exception Message: One or more errors occurred.
' Task Inner Exception Message: Something happened.
' Output when an OperationCanceledException or TaskCanceledException
' is thrown in the awaited method:
' Exception Message: canceled
' Task IsCanceled: True
' Task IsFaulted: False
非同期メソッドの複数の例外の処理
次の例では、複数のタスクで複数の例外が発生する可能性がある例外処理について説明します。 Try
ブロックには、Task.WhenAll で返されたタスクの Await
式が含まれています。 Task.WhenAll が適用される 3 つのタスクが完了すると、このタスクは完了します。
3 つのタスクでそれぞれ例外が発生します。 Catch
ブロックは例外を反復処理します。この例外は、Task.WhenAll
が返したタスクの Exception.InnerExceptions
プロパティで見つかります。
Public Async Function DoMultipleAsync() As Task
Dim theTask1 As Task = ExcAsync(info:="First Task")
Dim theTask2 As Task = ExcAsync(info:="Second Task")
Dim theTask3 As Task = ExcAsync(info:="Third Task")
Dim allTasks As Task = Task.WhenAll(theTask1, theTask2, theTask3)
Try
Await allTasks
Catch ex As Exception
Debug.WriteLine("Exception: " & ex.Message)
Debug.WriteLine("Task IsFaulted: " & allTasks.IsFaulted)
For Each inEx In allTasks.Exception.InnerExceptions
Debug.WriteLine("Task Inner Exception: " + inEx.Message)
Next
End Try
End Function
Private Async Function ExcAsync(info As String) As Task
Await Task.Delay(100)
Throw New Exception("Error-" & info)
End Function
' Output:
' Exception: Error-First Task
' Task IsFaulted: True
' Task Inner Exception: Error-First Task
' Task Inner Exception: Error-Second Task
' Task Inner Exception: Error-Third Task
関連項目
.NET