Оператор 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 перехватывает исключения только в том случаеTrue , если expression имеет значение . Предложение 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 . |
Комментарии
Если предполагается, что определенное исключение может возникнуть во время определенного раздела кода, поместите код в блок и используйте Catch
блок для сохранения элемента управления и обработки исключения в Try
случае возникновения.
Оператор 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. В диспетчере фрагментов кода разверните узел Code Patterns - If, For Each, Try Catch, Property и т. д., а затем — Обработка ошибок (исключения). Дополнительные сведения см. в статье Фрагменты кода.
Наконец, блок
Если у вас есть одна или несколько инструкций, которые необходимо выполнить перед выходом Finally
из Try
структуры, используйте блок . Управление передается блоку Finally
непосредственно перед тем, как он выходит из Try…Catch
структуры. Это верно, даже если исключение возникает в Try
любом месте структуры.
Блок Finally
полезен для выполнения любого кода, который должен выполняться, даже если есть исключение. Управление передается блоку Finally
независимо от того, как Try...Catch
он выходит.
Код в блоке Finally
выполняется, даже если код встречает инструкцию Return
в блоке Try
или Catch
. Элемент управления не передается из Try
блока или Catch
в соответствующий Finally
блок в следующих случаях:
В блоке
Try
илиCatch
обнаруживается оператор End.В StackOverflowException блоке
Try
илиCatch
возникает исключение .
Недопустимо явно передавать выполнение в Finally
блок. Передача выполнения из блока является недопустимой Finally
, за исключением исключения.
Try
Если инструкция не содержит хотя бы один Catch
блок, он должен содержать Finally
блок .
Совет
Если не требуется перехватывать определенные исключения, 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
, завершается, выполнение возобновляется в том же методе. Дополнительные сведения см. в разделе Поток управления в асинхронных программах.
Задача, возвращаемая асинхронным методом, может завершиться в состоянии сбоя, указывая на то, что она завершена из-за необработанного исключения. Задача также может завершиться в состоянии отмены, что приводит к выброшению OperationCanceledException
из выражения await. Чтобы перехватить исключение любого типа, поместите Await
выражение, связанное с задачей Try
, в блок и перехватите исключение в блоке Catch
. Пример приведен далее в этом разделе.
Задача может находиться в состоянии сбоя, так как за ее сбой отвечало несколько исключений. Например, задача может быть результатом вызова метода Task.WhenAll. Когда вы ожидаете такую задачу, перехватимое исключение является только одним из исключений, и вы не можете предсказать, какое исключение будет перехвачено. Пример приведен далее в этом разделе.
Выражение Await
не может находиться внутри Catch
блока или Finally
блока.
Iterators
Функция или метод доступа итератора выполняет пользовательскую итерацию Get
по коллекции. Итератор использует оператор Yield для возврата каждого элемента коллекции по одному. Вы вызываете функцию итератора с помощью for each... Следующая инструкция.
Оператор Yield
может находиться внутри Try
блока. Блок Try
, содержащий инструкцию Yield
, может иметь Catch
блоки и Finally
блок . Пример см. в разделе "Попробовать блоки в Visual Basic" статьи Итераторы .
Оператор Yield
не может находиться внутри Catch
блока или Finally
блока.
Если текст For Each
(за пределами функции итератора) вызывает исключение, Catch
блок в функции итератора не выполняется, но Finally
выполняется блок в функции итератора. Блок Catch
внутри функции итератора перехватывает только исключения, возникающие внутри функции итератора.
Ситуации частичного доверия
В ситуациях с частичным доверием, таких как приложение, размещенное в общей сетевой папке, не перехватывает исключения безопасности, Try...Catch...Finally
возникающие до вызова метода, содержащего вызов. В следующем примере, когда вы помещаете его в общую папку сервера и запускаете его оттуда, возникает ошибка "System.Security.SecurityException: Request Failed". Дополнительные сведения об исключениях безопасности см. в SecurityException классе .
Try
Process.Start("http://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... Поймать... Наконец
В следующем примере показана 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
Исключение в методе, вызываемом из блока 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
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
В следующем примере показано, как использовать 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
Обработка исключений для асинхронных методов
В следующем примере демонстрируется обработка исключений для асинхронных методов. Чтобы перехватить исключение, применимое к асинхронной задаче, Await
выражение находится в Try
блоке вызывающего объекта, а исключение перехватывается в блоке Catch
.
Раскомментируйте строку Throw New Exception
в этом примере для демонстрации обработки исключений. Исключение перехватится в блоке Catch
, свойству задачи IsFaulted
присваивается значение True
, а свойству задачи Exception.InnerException
присваивается исключение.
Раскомментируйте строку Throw New OperationCancelledException
, чтобы показать, что происходит при отмене асинхронного процесса. Исключение перехватится в блоке Catch
, а свойству задачи IsCanceled
присваивается значение True
. Однако при некоторых условиях, которые не относятся к этому примеру, для параметра задано значение True
, IsFaulted
а 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