Visual Basic の構造化例外処理の概要

更新 : 2008 年 7 月

Visual Basic は、構造化例外処理をサポートしています。構造化例外処理を使うと、信頼性が高く包括的なエラー ハンドラによって、プログラムの作成および管理を行うことができます。構造化例外処理とは、実行時にエラーの検出および処理を行うためのコードであり、制御構造 (Select Case や While に似た制御構造) と、例外、コードの保護ブロック、およびフィルタが組み合わされています。

Try...Catch...Finally ステートメントを使用すると、エラーが発生する可能性のあるコードのブロックを保護できます。例外ハンドラを入れ子にすることもできます。この場合、それぞれのブロックで宣言した変数は、ローカル スコープを持ちます。

Try...Catch...Finally ステートメント

Try...Catch...Finally ステートメントの構造体を、次のコードに示します。

Try
    ' Starts a structured exception handler.
    ' Place executable statements that may generate 
    ' an exception in this block.
Catch '[optional filters]
    ' This code runs if the statements listed in 
    ' the Try block fail and the filter on the Catch statement is true.
'[Additional Catch blocks]
Finally
    ' This code always runs immediately before
    ' the Try statement exits.
End Try
' Ends a structured exception handler.

Try...Catch...Finally 例外ハンドラの Try ブロックには、例外が監視されるコードのセクションが含まれています。このセクションの実行中にエラーが発生した場合、そのエラーに一致する条件が見つかるまで、Try...Catch...Finally 内のそれぞれの Catch ステートメントが Visual Basic によって調べられます。一致が見つかった場合、その Catch ブロックの最初の行に制御が移ります。一致する Catch ステートメントが見つからなかった場合は、例外が発生したブロックの外側にある Try...Catch...Finally ブロックの Catch ステートメントが検索されます。このプロセスは、現在のプロシージャで一致する Catch ブロックが見つかるまで、スタック全体にわたって続けられます。一致が見つからなかった場合は、エラーが生成されます。

Finally セクション内のコードは、Catch ブロック内のコードが実行されたかどうかに関係なく、常に最後 (エラー処理ブロックがスコープを失う直前) に実行されます。Finally セクションには、クリーンアップ コード (ファイルを閉じたりオブジェクトを解放したりするコードなど) を配置します。例外をキャッチする必要はないけれども、リソースをクリーンアップする必要がある場合、Finally セクションではなく、Using ステートメントを使用します。詳細については、「Using ステートメント (Visual Basic)」を参照してください。

Catch ブロックにおけるエラーのフィルタ処理

Catch ブロックで特定のエラーをフィルタ処理するには、3 とおりの方法があります。まず、次のように、例外のクラス (次の例では ClassLoadException) に基づいてエラーをフィルタ処理する方法があります。

Try
    ' "Try" block.
Catch e as ClassLoadException
    ' "Catch" block.
Finally
    ' "Finally" block.
End Try

ClassLoadException エラーが発生すると、指定した Catch ブロック内のコードが実行されます。

エラーをフィルタ処理する 2 番目の方法では、Catch セクションで任意の条件式をフィルタ処理できます。この型の Catch フィルタは、たとえば次のコードのように、特定のエラー番号をテストする場合などによく使用されます。

Try
   ' "Try" block.
Catch When ErrNum = 5 'Type mismatch.
   ' "Catch" block.
Finally
   ' "Finally" block.
End Try

一致するエラー ハンドラが Visual Basic で見つかると、そのハンドラ内のコードが実行され、Finally ブロックに制御が渡されます。

8a9f2ew0.alert_note(ja-jp,VS.90).gifメモ :

例外を処理するために Catch ブロックを見つけるときには、一致が見つかるまで各ブロックのハンドラが評価されます。これらのハンドラは関数の呼び出しである場合もあるため、予期しない副作用が起こることがあります。たとえば、そのような呼び出しによってパブリック変数が変更され、後でその変数が、最終的に例外を処理する別の Catch ブロックのコードで使用される場合があります。

3 番目の方法として、1 番目と 2 番目の方法を組み合わせ、両方を使用して例外処理を行うこともできます。Catch ステートメントの特定性を最大から最小に移行する必要があります。Catch ブロック自体は、Exception から派生したすべての例外をキャッチします。したがって、常に Finally の前の、最後のブロックである必要があります。

Try…Catch ブロックの分岐

Catch ブロックから、最初の Try ステートメントまたは End Try ステートメントに分岐することは可能です。しかし、囲まれた TrycCatch ブロック内への分岐はできません。これについて、次に示します。

Try キャッチ分岐

構造化例外処理の例

Try...Catch...Finally ステートメントを使った単純なエラー ハンドラの例を次に示します。

Option Strict On
Imports System.IO

Module Module1
    Private Const FileName As String = "TestFile.data"

    Public Sub Main()

        ' First, create a new data file and write some data to the file.
        ' 1. Create the new, empty data file.
        If File.Exists(FileName) Then
            File.Delete(FileName)
        End If
        Dim fs As New FileStream(FileName, FileMode.CreateNew)

        ' 2. Create a BinaryWriter object for the data.
        Dim writer As New BinaryWriter(fs)

        ' 3. Write some sample data to the file.
        For i = 0 To 10
            writer.Write(i)
        Next i
        writer.Close()
        fs.Close()

        ' Now read from the file you just made.
        ' 1. Create a BinaryReader object for the data stream.
        fs = New FileStream(FileName, FileMode.Open, FileAccess.Read)
        Dim reader As New BinaryReader(fs)

        ' 2. Read data from TestFile.data. The loop terminates with an
        ' EndOfStreamException when an attempt is made to read past
        ' the end of the stream.
        Try
            ' This loop terminates with an EndOfStreamException when it 
            ' reaches the end of the stream.
            While True
                Console.WriteLine(reader.ReadInt32())
            End While
            Console.WriteLine("The data was read with no error.")
        ' 3. Report the first error that is caught, if there is one.
        Catch eosExcep As EndOfStreamException
            ' This Catch block is executed when the reader attempts
            ' to read past the end of the stream.
            Console.WriteLine("End-of-stream exception occurred.")
        Catch IOExcep As System.IO.IOException
            ' For this Catch block, some other error occurred before
            ' the end of stream was reached. Print the standard
            ' exception message.
            Console.WriteLine(IOExcep.Message)
        Finally
            ' The Finally block is always executed.
            Console.WriteLine("Executing the Finally block.")
            reader.Close()
            fs.Close()
        End Try
    End Sub

End Module

Finally ブロックは、前の各 Catch ブロックで行われた動作に関係なく、常に実行されます。構造化例外処理で Resume または Resume Next を使用することはできません。

8a9f2ew0.alert_note(ja-jp,VS.90).gifメモ :

前の例では、IOException クラスや EndOfStreamException クラス以外の例外は、処理されずに呼び出し元に戻されます。

参照

処理手順

例外処理のトラブルシューティング

概念

例外処理の概要

エラーの種類

非構造化例外処理の概要

参照

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

BinaryReader

BinaryWriter

FileStream

その他の技術情報

例外処理のタスク

履歴の変更

日付

履歴

理由

2008 年 7 月

「構造化例外処理の例」セクションの例を置き換え。

カスタマ フィードバック