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 區塊時,如果發生例外狀況 (Exception),則會按文字順序檢查每一個 Catch 陳述式,以判斷它是否會利用代表已擲回之例外狀況的 exception 來處理例外狀況。

exception

選擇項。 任何變數名稱。 exception 的初始值就是擲回的錯誤值。 與 Catch 搭配使用以指定攔截的錯誤。 如果省略,則 Catch 陳述式會攔截所有例外狀況。

type

選擇項。 指定類別篩選條件類型。 如果 exception 的值為 type 所指定的型別或衍生型別 (Derived Type),則識別項會繫結到例外狀況物件。

When

選擇項。 只有在 expression 評估為 True 時,具有 When 子句的 Catch 陳述式才會攔截例外狀況。 只有在檢查例外狀況的型別之後,才會套用 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 陳述式是由其後跟隨一個或多個指定各種例外狀況處理常式之 Catch 子句的 Try 區塊組成。 當 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...Finally 結構外宣告該變數。

秘訣秘訣

Try…Catch…Finally 陳述式可用來做為 IntelliSense 程式碼片段。 在 [程式碼片段管理員] 中,依序展開 [程式碼模式 - If、For Each、Try Catch、Property 等] 和 [錯誤處理 (例外狀況)]。 如需詳細資訊,請參閱HOW TO:插入 IntelliSense 程式碼片段

Finally 區塊

如果必須先執行一或多個陳述式再結束 Try 結構,請使用 Finally 區塊。 控制項會先傳遞至 Finally 區塊,再從 Try…Catch 結構傳出。 即使 Try 結構內部的任何位置發生例外狀況 (Exception),也會執行這個動作。

Finally 區塊可用於執行即使發生例外狀況都必須執行的任何程式碼。 不論 Try...Catch 區塊如何結束,程式執行都會轉移到 Finally 區塊。

即使您的程式碼在 Try 或 Catch 區塊中遇到 Return 陳述式,Finally 區塊中的程式碼仍會執行。 在下列情況下,不會將控制項從 Try 或 Catch 區塊傳遞至對應的 Finally 區塊:

將執行轉送至 Finally 區塊是無效的。 在 Finally區塊以外轉換執行也是無效的,透過例外狀況除外。

如果 Try 陳述式未包含至少一個 Catch 區塊,它必須包含一個 Finally 區塊。

秘訣秘訣

如果不需要攔截特定例外狀況,則 Using 陳述式的行為會像 Try…Finally 區塊,而且不論是以何種方式結束該區塊,都保證會處置 (Dispose) 資源。 即使在未處理例外狀況的情況下也一樣。 如需詳細資訊,請參閱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: Request Failed"。如需安全性例外狀況的詳細資訊,請參閱 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 進行的初始呼叫將會失敗。 這會使得包含 Process.Start 的 Sub 開始之前,且在產生安全性例外狀況之前,讓 Try...Catch 攔截到這項錯誤。

範例

下列範例說明 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 方法不會處理例外狀況。 由於對 CreateException 方法的呼叫是在 Try 區塊中進行的,因此RunSample 方法不會處理例外狀況。

範例包含許多例外狀況類型的 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 月

已重新組織並加入至備註,而且已加入範例。

資訊加強。