Оператор 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

Необязательный параметр. Инструкция Catch с предложением When перехватывает исключения, только если результат вычисления 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.

Заметки

Если предполагается, что во время выполнения определенного раздела кода может возникнуть определенное исключение, то поместите код в блок Try и используйте блок Catch для сохранения управления и обработки возникшего исключения.

Оператор try-catch Try…Catch состоит из блока Try, за которым следует одно или несколько предложений Catch, в которых определяются обработчики для различных исключений. Когда текущее исключение выбрасывается в блоке Try, Visual Basic ищет оператор Catch, обрабатывающий исключение. Если не найден соответствующий оператор Catch, Visual Basic рассматривается метод, который вызвал текущий метод, и так далее вверх по стеку вызовов. Если блок Catch не найден, то среда Visual Basic отображает пользователю сообщение о необработанном исключении и останавливает выполнение программы.

Можно использовать более одного оператора Catch в операторе Try…Catch. В этом случае будет иметь значение порядок следования предложений Catch, поскольку предложения будут проверяться именно в этом порядке. Более общие исключения следует перехватывать после более частных.

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

  • type имеет значение Exception, например Catch ex As Exception.

  • Оператор не имеет переменной exception, например Catch.

Когда оператор Try…Catch…Finally вложен в другой блок Try , Visual Basic сначала проверяет каждый оператор Catch во внутреннем блоке Try . Если соответствующий оператор Catch не найден, поиск продолжается в операторах Catch внешнего блока Try…Catch…Finally.

Локальные переменные блока Try недоступны в блоке Catch, поскольку это отдельные блоки. Если нужно использовать переменную в нескольких блоках, то следует объявить ее вне структуры Try...Catch...Finally.

Совет

Оператор Try…Catch…Finally доступен также в качестве фрагмента кода IntelliSense.В Диспетчере фрагментов кода, разверните Шаблоны кода - If, For Each, Try Catch, Property, и т.д.и затем Обработка ошибок (исключения) .Дополнительные сведения см. в разделе Фрагменты кода.

Блок finally

Если имеется одна или несколько инструкций, которые необходимо запустить до выхода из структуры Try, используйте блок Finally. Элемент управления передает в блок Finally только перед передачей из структуры Try…Catch. Это справедливо даже в том случае, если исключение возникает внутри структуры Try.

Finally Блок является полезным для запуска любой код, который должен выполняться, даже если есть исключение. Управление всегда передается блоку Finally независимо от того, как была выполнен выход из блока Try...Catch.

Код в блоке Finally выполняется, даже если ваш код встречает оператор Return в блоке Try или Catch. Элемент управления не передает из блока Try или блока Catch в соответствующий блок Finally в следующих случаях:

Он является недопустимым явного для получения выполнения в блоке Finally. Переключиться из блока выполнение Finally является недопустимым, за исключением через исключения.

Если инструкция Try не содержит ни одного блока Catch, то она должна содержать Finally.

Совет

Если не требуется перехватывать определенные исключения, оператор Using действует аналогично блоку Try…Finally и гарантирует освобождение ресурсов независимо от способа выхода из блока.Это справедливо даже в случае необработанного исключения.Дополнительные сведения см. в разделе Оператор Using (Visual Basic).

Аргументы исключения

Catch блокирует аргумент exception, который представляет собой экземпляр класса Exception или класса, производного от класса Exception. Экземпляр класса Exception соответствует возникшей в блоке Try ошибке.

Свойства объекта Exception помогают в определении причины и места возникновения исключений. Например, свойство StackTrace содержит список вызванных методов, которые привели к исключению, помогая обнаружить место возникновения ошибки в коде. Message возвращает сообщение, описывающее исключение. HelpLink возвращает ссылку на связанный файл справки. InnerException возвращает объектException , который вызвал текущее исключение, или оно возвращает Nothing, если нет никакой первоначальной Exception.

Соображения при использовании оператора 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

Если пометить метод с модификатором Async, можно использовать оператор подождите в методе. Выписка с оператором Await приостанавливает выполнение методов до тех пор, пока подожданная задача не завершится. Задача представляет текущие работы. Задача, которая связана с оператором Await завершает выполнение возобновляется в одном методе. Дополнительные сведения см. в разделе Поток управления в асинхронных программах (C# и Visual Basic).

Задача, возвращаемая методом Async может быть выполнен в состоянии сбоя, что указывает на то, что она была завершена из-за необработанного исключения. Задача также может завершиться в отмененном состоянии, которое приводит к тому, OperationCanceledException возникающем из выражения ожидания. Для перехвата любой тип исключения, поместите выражения Await, связанный с задачей в блоке Try и перехватывать исключения в блоке Catch. Пример приведен ниже.

Задача может находиться в состоянии сбоя, так как несколько исключений, ответственные за его ошибаться. Например, задача может быть результатом вызова метода Task.WhenAll. Если ожидается такой задачи, обнаружено исключение только одно из исключений, и невозможно предсказать, перехватывается исключение будет. Пример приведен ниже.

Выражение не может быть Await внутри блока Catch или блока Finally.

Итераторы

Функция итератора или метод доступа Get выполняет пользовательскую итерацию по коллекции. Итератор выписку Выходные данные используется для возвращения каждый элемент коллекции одной записи за раз. Вызовите функцию итератора с помощью Оператор For Each... Next (Visual Basic).

Оператор Yield может быть внутри блока Try. Блок Try, содержащий выписку Yield может содержать блоки Catch и может содержать блок Finally. Блоки try см. в разделе Visual Basic" Итераторы (C# и Visual Basic) для примера.

Оператор Yield не может быть Catch блока или внутри блока Finally.

Если тело For Each (за пределами функции итератора) создает исключение, оно не выполняется Catch в блок функции итератора, но выполняется в блок Finally функции итератора. Блок 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 не удастся. Это позволяет Try...Catch перехватить вызов перед началом выполнения Sub, которая содержит Process.Start, и создаст исключение безопасности.

Пример

В следующем примере показано структура оператора 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 не обрабатывает исключение. Метод RunSample обрабатывает исключение, поскольку вызов метода CreateException находится в блоке Try.

Пример включает операторы 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…Catch , который содержится в блоке Try . Внутренний блок 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

Следующий пример иллюстрирует обработку ошибок для асинхронных методов. Для перехвата исключения, которое применяется к задаче async выражение Await в блоке Try вызывающей стороны, и исключение перехватывается в блоке Catch.

Раскомментируйте линия Throw New Exception в примере для демонстрации обработку ошибок. Исключение перехватывается в блоке Catch, свойство IsFaulted задачи устанавливается в True, а свойство Exception.InnerException задачи устанавливается на исключение.

Раскомментируйте линия Throw New OperationCancelledException для демонстрации того, что происходит при отмене асинхронный процесс. Исключение перехватывается в блоке Catch, а свойство IsCanceled задачи устанавливается в True. Однако при определенных условиях, которые не применяются к данному примеру 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 содержит выражение Await для задачи, которую Task.WhenAll возвращен. Задача завершена, когда 3 задачи, к которой применяется Task.WhenAll.

Каждая из задач 3 причин исключения. Блок Catch перебирает исключения, которые находятся в свойстве Exception.InnerExceptions задачи, которую Task.WhenAll возвращен.

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

См. также

Ссылки

Err

Оператор Exit (Visual Basic)

Оператор On Error (Visual Basic)

Exception

Оператор Throw (Visual Basic)

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

Рекомендации по использованию фрагментов кода

Обработка исключений (библиотека параллельных задач)