Visual Basic 的結構化例外處理概觀

更新: 2008 年 7 月

Visual Basic 支援結構化例外處理 (Structured Exception Handling),可幫助您使用強大、全面性的錯誤處理常式來建立和維護程式。結構化例外處理是一種程式碼,將控制結構 (類似於 Select Case 或 While) 與例外狀況、受保護的程式碼區塊和篩選條件結合,以偵測並回應執行時所發生的錯誤。

使用 Try...Catch...Finally 陳述式可以保護有可能引發錯誤的程式碼區塊。您可以將例外處理常式巢狀化,而您在每一個區塊所宣告的變數會擁有區域範圍 (Local Scope)。

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 例外處理常式 (Exception Handler) 中,Try 區塊所包含的程式碼區段會受到監視,確定是否發生例外狀況。如果在執行這個區段時發生錯誤,Visual Basic 會檢查 Try...Catch...Finally 中的每個 Catch 陳述式,直到找到條件與錯誤符合的陳述式。如果找到符合的陳述式,控制權會轉換到 Catch 區塊的第一行程式碼。如果找不到相符的 Catch 陳述式,則會繼續搜尋外部 Try...Catch...Finally 區塊 (即內含發生例外狀況的區塊),以找出相符的 Catch 陳述式。以上的步驟會在整個堆疊中持續進行,直到在目前的程序中找到符合的 Catch 區塊為止。如果找不到相符的區塊,就會產生錯誤。

Finally 區段中的程式碼永遠是最後執行的,也就是在錯誤處理區塊範圍結束之前,不論 Catch 區塊中的程式碼是否已執行。請清除在 Finally 區段的程式碼 (例如關閉檔案並釋出物件的程式碼)。如果您不需要攔截例外狀況,但必須清除資源,可以考慮使用 Using 陳述式,而非 Finally 區段。如需詳細資訊,請參閱 Using 陳述式 (Visual Basic)

Catch 區塊中的錯誤篩選

Catch 區塊可使用三種選項來篩選特定錯誤。在其中一種選項中,錯誤會根據例外狀況的類別加以篩選 (在這裡是 ClassLoadException),如下列程式碼所示。

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

如果發生了 ClassLoadException 錯誤,就會執行所指定 Catch 區塊內的程式碼。

在第二個篩選錯誤的選項中,Catch 區段可篩選任何條件運算式。這種 Catch 篩選方法常用來測試特定的錯誤代碼,如下列程式碼所示。

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

當 Visual Basic 找到符合的錯誤處理常式時,就會執行該處理常式中的程式碼,再將控制權傳送至 Finally 區塊。

注意事項:

當試著尋找 Catch 區塊來處理例外狀況時,會評估每個區塊的處理常式,直到找到符合的項目為止。由於這些處理常式都可用來呼叫函式,因此可能會發生未能預期的副作用,例如,這類的呼叫會變更公用變數,但另一個 Catch 區塊的程式碼也使用該公用變數,最後就變成是由這個區塊處理例外狀況。

第三個選項是結合選項一與選項二,將二者都用來處理例外狀況。Catch 陳述式應該從最特定移至最不特定的。Catch 區塊會自行攔截所有從 Exception 衍生的例外狀況,所以它必須永遠是在 Finally 之前的最後區塊。

Try…Catch 區塊的分支

Catch 區塊的分支可以回到原來的 Try 陳述式或 End Try 陳述式,但無法分支到封閉的 Try¡KCatch 陳述式。以下說明這種情況:

Try Catch 分支

結構化例外處理常式範例

下列範例顯示另一個使用 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

無論前面的 Catch 區塊執行任何動作,最後都一定會執行 Finally 區塊。您無法在結構化例外處理中使用 Resume 或 Resume Next

注意事項:

在前面的範例中,任何 IOException 類別或 EndOfStreamException 類別以外的例外狀況都會直接傳回呼叫端而不加以處理。

請參閱

工作

例外處理疑難排解

概念

例外處理簡介

錯誤類型

非結構化例外處理概觀

參考

Try...Catch...Finally 陳述式 (Visual Basic)

BinaryReader

BinaryWriter

FileStream

其他資源

例外處理工作

變更記錄

日期

記錄

原因

2008 年 7 月

取代「結構化例外處理常式範例」一節中的範例。

客戶回函。