Обзор структурной обработки исключений в Visual Basic

Обновлен: Июль 2008

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 обработчика исключений Try...Catch...Finally содержит раздел кода, которая контролируется на предмет исключений. Если во время выполнения этого раздела возникает ошибка, Visual Basic проверяет каждый оператор в Catch внутри Try...Catch...Finally, пока не обнаружит условие, которое соответствует этой ошибке. При обнаружении такого условия управление передается первой строке кода в блоке Catch. Если соответствующий оператор Catch не найден, поиск продолжается в операторах Catch внешнего блока Try...Catch...Finally, который содержит блок, в котором возникло исключение. Этот процесс продолжается по всему стеку, пока не будет обнаружен соответствующий блок 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.

8a9f2ew0.alert_note(ru-ru,VS.90).gifПримечание.

При поиске блока Catch для обработки исключения рассматриваются обработчики каждого блока, пока не обнаружится совпадение. Так как эти обработчики могут быть вызовами функций, вероятны нежелательные побочные эффекты: например, такой вызов может изменить открытую переменную, которая затем используется в коде другого блока Catch, который в конечном счете будет обрабатывать данное исключение.

Третий вариант — это сочетание первых двух и их совместное использование для обработки исключений. Операторы Catch должны располагаться в порядке от наиболее конкретных к более общим. Сам блок Catch будет перехватывать все исключения, производные от Exception, и, следовательно, всегда должен быть последним блоком перед Finally.

Выход из блоков Try…Catch путем ветвления

Из блока Catch можно путем ветвления перейти в исходный оператор Try или End Try, но не в содержащий его блок Try…Catch. Это показано ниже:

Ветвление 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

Блок Finally выполняется всегда, независимо от каких-либо действий, выполненных в предыдущих блоках Catch. Операторы Resume и Resume Next нельзя использовать в структурной обработке исключений.

8a9f2ew0.alert_note(ru-ru,VS.90).gifПримечание.

В предыдущем примере любое исключение, отличное от класса IOException или EndOfStreamException, передается без обработки назад в вызывающий код.

См. также

Задачи

Устранение неполадок при обработке исключений

Основные понятия

Введение в обработку исключений

Типы ошибок

Обзор неструктурной обработки исключений

Ссылки

Оператор Try... Catch... Finally (Visual Basic)

BinaryReader

BinaryWriter

FileStream

Другие ресурсы

Задачи обработки исключений

Журнал изменений

Дата

Журнал изменений

Причина

Июль 2008

Замените пример в подразделе "Пример структурного обработчика исключений".

Обратная связь от клиента.