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
блоке Visual Basic ищет Catch
инструкцию, обрабатывающую исключение. Если оператор сопоставления Catch
не найден, Visual Basic проверяет метод, вызывающий текущий метод, и т. д. Если блок не Catch
найден, Visual Basic отображает необработанное сообщение об исключении для пользователя и останавливает выполнение программы.
В инструкции можно использовать несколько Catch
инструкций Try…Catch
. Если это сделать, порядок Catch
предложений является значительным, так как они проверяются в порядке. 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, TryCatchProperty и т. д., а затем Обработка ошибок (исключения). Для получения дополнительной информации см. Code Snippets.
Блок Finally
Если у вас есть одна или несколько инструкций, которые должны выполняться перед выходом Try
Finally
из структуры, используйте блок. Элемент управления передается Finally
блоку непосредственно перед тем, как он выходит из Try…Catch
структуры. Это верно, даже если исключение происходит в любой точке Try
структуры.
Блок Finally
полезен для выполнения любого кода, который должен выполняться, даже если существует исключение. Элемент управления передается блоку Finally
независимо от Try...Catch
способа выхода блока.
Код в блоке Finally
выполняется, даже если код встречает Return
инструкцию в блоке Try
или Catch
блоке. Элемент управления не передается из Try
блока или Catch
блока в соответствующий Finally
блок в следующих случаях:
Оператор End обнаруживается в блоке или
Catch
блокеTry
.Вызывается StackOverflowException в блоке
Try
илиCatch
блоке.
Недопустимо явно передавать выполнение в Finally
блок. Передача выполнения из Finally
блока недопустима, за исключением исключения.
Try
Если оператор не содержит хотя бы один Catch
блок, он должен содержать Finally
блок.
Совет
Если у вас нет catch определенных исключений, Using
инструкция ведет себя как Try…Finally
блок и гарантирует удаление ресурсов независимо от способа выхода из блока. Это верно даже с необработанным исключением. Дополнительные сведения см. в разделе Оператор using.
Аргумент исключения
Аргумент Catch
блока exception
— это экземпляр класса или класса, производный Exception от Exception
класса. Экземпляр Exception
класса соответствует ошибке, которая произошла в блоке Try
.
Свойства Exception
объекта помогают определить причину и расположение исключения. Например, StackTrace свойство перечисляет вызываемые методы, которые привели к исключению, помогая определить, где произошла ошибка в коде. Message возвращает сообщение, описывающее исключение. HelpLink возвращает ссылку на связанный файл справки. InnerExceptionException
возвращает объект, вызвавшее текущее исключение, или возвращается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 , можно использовать оператор Await в методе. Оператор с оператором Await
приостанавливает выполнение метода до завершения ожидаемой задачи. Задача представляет выполняющуюся работу. Когда задача, связанная с оператором Await
, завершается, выполнение возобновляется в том же методе. Дополнительные сведения см. в разделе "Поток управления" в асинхронных программах.
Задача, возвращаемая методом Async, может завершиться сбоем, указывая на то, что она завершена из-за необработанного исключения. Задача также может завершиться в отмененном состоянии, что приводит к OperationCanceledException
возникновению исключения из выражения await. Для catch любого типа исключения поместите Await
выражение, связанное с задачей в Try
блоке, и catch исключение в блоке Catch
. Пример представлен далее в этом разделе.
Задача может находиться в состоянии сбоя, так как несколько исключений отвечают за его сбой. Например, задача может быть результатом вызова метода Task.WhenAll. Когда вы ожидаете такую задачу, выловленное исключение является только одним из исключений, и вы не можете предсказать, какое исключение будет поймано. Пример представлен далее в этом разделе.
Выражение Await
не может находиться внутри Catch
блока или Finally
блока.
Итераторы
Функция итератора или Get
метод доступа выполняет настраиваемую итерацию по коллекции. Итератор использует инструкцию Yield для возврата каждого элемента коллекции по одному за раз. Вы вызываете функцию итератора с помощью элемента For Each... Следующая инструкция.
Оператор Yield
может находиться внутри Try
блока. Блок Try
, содержащий инструкцию Yield
, может иметь Catch
блоки и может иметь Finally
блок. Пример см. в разделе Try "Блоки".
Оператор Yield
не может находиться внутри Catch
блока или Finally
блока.
For Each
Если тело (вне функции итератора) создает исключение, Catch
блок в функции итератора не выполняется, но Finally
выполняется блок в функции итератора. Блок Catch
внутри функции итератора перехватывает только исключения, происходящие внутри функции итератора.
Ситуации с частичным доверием
В ситуациях с частичным доверием, таких как приложение, размещенное в общей сетевой папке, Try...Catch...Finally
не catch вызывает исключения безопасности, возникающие перед вызовом метода, содержащего вызов. В следующем примере, когда вы помещаете его в общую папку сервера и запускаете его оттуда, возникает ошибка System.Security.SecurityException: Request Failed. Дополнительные сведения об исключениях безопасности см. в SecurityException классе.
Try
Process.Start("http://www.microsoft.com")
Catch ex As Exception
Console.WriteLine("Can't load Web page" & vbCrLf & ex.Message)
End Try
В такой ситуации с частичным доверием необходимо поместить инструкцию Process.Start
в отдельный Sub
. Первоначальный вызов Sub
сбоя. Это позволяет Try...Catch
catch ему перед запуском Sub
и Process.Start
созданием исключения безопасности.
Примеры
Структура Try...Catch...Finally
В следующем примере показана структура инструкции 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.
Console.WriteLine("end of Try block")
Catch ex As Exception
' Show the exception's message.
Console.WriteLine(ex.Message)
' Show the stack trace, which is a list of methods
' that are currently executing.
Console.WriteLine("Stack Trace: " & vbCrLf & ex.StackTrace)
Finally
' This line executes whether or not the exception occurs.
Console.WriteLine("in Finally block")
End Try
End Sub
Исключение в методе, вызываемом Try
из блока
В следующем примере 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
Console.WriteLine("NullReferenceException: " & ex.Message)
Console.WriteLine("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
Оператор When Catch
В следующем примере показано, как использовать 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
инструкция, содержащаяся в блоке 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
Обработка исключений для асинхронных методов
В следующем примере демонстрируется обработка исключений для асинхронных методов. Исключение catch , которое применяется к асинхронной задаче, Await
выражение находится в Try
блоке вызывающего объекта, и исключение перехватится в блоке Catch
.
Раскомментируйте строку Throw New Exception
в этом примере для демонстрации обработки исключений. Исключение поймано в блокеCatch
, свойство задачи имеет True
значение , а свойство задачи IsFaulted
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 . Задача завершается, когда выполняются три задачи, к которым Task.WhenAll применяются.
Каждая из трех задач вызывает исключение. Блок 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