Try...Catch...Finally Instruction (Visual Basic)
Offre la possibilité de gérer certaines ou toutes les erreurs de se produire dans un bloc de code donné, tout en poursuivant l'exécution du code.
Syntaxe
Try
[ tryStatements ]
[ Exit Try ]
[ Catch [ exception [ As type ] ] [ When expression ]
[ catchStatements ]
[ Exit Try ] ]
[ Catch ... ]
[ Finally
[ finallyStatements ] ]
End Try
Éléments
Terme | Définition |
---|---|
tryStatements |
Optionnel. Instructions dans lesquelles peut se produire une erreur. Il peut s'agir d'une instruction composée. |
Catch |
Optionnel. Plusieurs blocs Catch autorisés. Si une exception se produit lors du traitement du bloc Try , chaque instruction Catch est examinée en texte pour déterminer si elle gère l’exception, avec exception représentant l’exception levée. |
exception |
Optionnel. Tout nom de variable. La valeur initiale de l'argument exception est la valeur de l'erreur levée. Utilisé avec Catch pour spécifier l’erreur interceptée. Si elle est omise, l’instruction Catch intercepte une exception. |
type |
Optionnel. Spécifie le type de filtre de classe. Si la valeur de exception est du type spécifié par type ou d’un type dérivé, l’identificateur devient lié à l’objet d’exception. |
When |
Optionnel. Une instruction Catch avec une clause When intercepte les exceptions uniquement lorsque expression est évaluée à True . Une clause When est appliquée uniquement après avoir vérifié le type de l’exception et expression peut faire référence à l’identificateur représentant l’exception. |
expression |
Optionnel. Doit être implicitement convertible en Boolean . Toute expression qui décrit un filtre générique. Généralement utilisé pour filtrer par numéro d’erreur. Utilisé avec un mot clé When pour spécifier les circonstances dans lesquelles l’erreur est interceptée. |
catchStatements |
Optionnel. Instruction(s) pour gérer les erreurs qui se produisent dans le bloc Try associé. Il peut s'agir d'une instruction composée. |
Exit Try |
Optionnel. Mot clé qui s’interrompt de la structure Try...Catch...Finally . L’exécution reprend avec le code immédiatement après l’instruction End Try . L’instruction Finally est toujours exécutée. Non autorisé dans les blocs Finally . |
Finally |
Optionnel. Un bloc Finally est toujours exécuté lorsque l’exécution quitte une partie de l’instruction Try...Catch . |
finallyStatements |
Optionnel. Instructions exécutées après l’exécution de tous les autres traitements d’erreurs. |
End Try |
Met fin à la structure Try...Catch...Finally . |
Notes
Si vous vous attendez à ce qu’une exception particulière se produise pendant une section de code particulière, placez le code dans un bloc Try
et utilisez un bloc Catch
pour conserver le contrôle et gérer l’exception si elle se produit.
L'instruction Try…Catch
consiste en un bloc Try
suivi d'une ou plusieurs clauses Catch
qui spécifient des gestionnaires pour différentes exceptions. Lorsqu’une exception est levée dans un bloc Try
, Visual Basic recherche l’instruction Catch
qui gère l’exception. Si une instruction correspondante Catch
est introuvable, Visual Basic examine la méthode appelée méthode actuelle, et ainsi de suite sur la pile des appels. Si aucun bloc Catch
n'est trouvé, Visual Basic affiche un message d'exception non gérée à l'utilisateur et arrête l'exécution du programme.
Vous pouvez utiliser plusieurs instructions Catch
dans une instruction Try…Catch
. Si vous faites cela, l’ordre des clauses Catch
est important parce qu’ils sont examinés dans l’ordre. Interceptez avec l’instruction Catch les exceptions les plus spécifiques avant les moins spécifiques.
Les conditions de l’instruction Catch
suivantes sont les moins spécifiques et vont catch toutes les exceptions qui dérivent de la classe Exception. Vous devez généralement utiliser l’une de ces variantes comme dernier bloc Catch
de la structure Try...Catch...Finally
, après avoir intercepté toutes les exceptions spécifiques attendues. Le flux de contrôle ne peut jamais atteindre un bloc Catch
qui suit l’une de ces variantes.
type
estException
, par exemple :Catch ex As Exception
L’instruction n’a aucune variable
exception
, par exemple :Catch
Lorsqu’une instruction Try…Catch…Finally
est imbriquée dans un autre bloc Try
, Visual Basic examine d’abord chaque instruction Catch
dans le bloc Try
le plus interne. Si aucune instruction Catch
correspondante n’est trouvée, la recherche passe aux instructions Catch
du bloc externe Try…Catch…Finally
.
Les variables locales d’un bloc Try
ne sont pas disponibles dans un bloc Catch
, car elles sont des blocs distincts. Si vous souhaitez utiliser une variable dans plusieurs blocs, déclarez la variable en dehors de la structure Try...Catch...Finally
.
Conseil
L’instruction Try…Catch…Finally
est disponible en tant qu’extrait de code IntelliSense. Dans le Gestionnaire d’extraits de code, développez Modèles de code : If, For Each, TryCatch, Property, etc, puis Gestion des erreurs (exceptions). Pour plus d’informations, consultez Extraits de code.
Bloc Finally
Si vous avez une ou plusieurs instructions qui doivent s’exécuter avant de quitter la structure Try
, utilisez un bloc Finally
. Le contrôle passe au bloc Finally
juste avant de sortir de la structure Try…Catch
. Cela est vrai même si une exception se produit n’importe où dans la structure Try
.
Un bloc Finally
est utile pour exécuter tout code qui doit s’exécuter même s’il existe une exception. Le contrôle est passé au bloc Finally
, quel que soit le mode de sortie du bloc Try...Catch
.
Le code d’un bloc Finally
s’exécute même si votre code rencontre une instruction Return
dans un bloc Try
ou Catch
. Le contrôle ne passe pas d’un bloc Try
ou Catch
bau bloc correspondant Finally
dans les cas suivants :
Une instruction End est rencontrée dans le bloc
Try
ouCatch
.StackOverflowException est levée dans le bloc
Try
ouCatch
.
Il n’est pas valide de transférer explicitement l’exécution dans un bloc Finally
. Le transfert de l’exécution hors d’un bloc Finally
n’est pas valide, sauf par le biais d’une exception.
Si une instruction Try
ne contient pas au moins un bloc Catch
, elle doit contenir un bloc Finally
.
Conseil
Si vous ne devez pas catch des exceptions spécifiques, l’instruction Using
se comporte comme un bloc Try…Finally
et garantit l'élimination des ressources, quelle que soit la façon dont vous sortez du bloc. Cela est vrai même avec une exception non gérée. Pour plus d’informations, consultez using, instruction.
Argument d’exception
L’argument de bloc Catch
exception
est une instance de la classe Exception ou d’une classe qui dérive de la classe Exception
. L’instance de classe Exception
correspond à l’erreur qui s’est produite dans le bloc Try
.
Les propriétés de l’objet Exception
permettent d’identifier la cause et l’emplacement d’une exception. Par exemple, la propriété StackTrace répertorie les méthodes appelées qui ont conduit à l’exception, ce qui vous aide à trouver où l’erreur s’est produite dans le code. Message retourne un message qui décrit l'exception. HelpLink retourne un lien vers un fichier d’aide associé. InnerException retourne l’objet Exception
qui a provoqué l’exception actuelle, ou il retourne Nothing
s’il n’y a pas de Exception
d’origine.
Considérations relatives à l’utilisation d’une instruction Try…Catch
Utilisez une instruction Try…Catch
uniquement pour signaler l’occurrence d’événements de programme inhabituels ou imprévus. Les raisons suivantes sont les suivantes :
L’interception des exceptions au moment de l’exécution crée une surcharge supplémentaire et est susceptible d’être plus lente que la pré-vérification pour éviter les exceptions.
Si un bloc
Catch
n’est pas géré correctement, l’exception peut ne pas être signalée correctement aux utilisateurs.La gestion des exceptions rend un programme plus complexe.
Vous n’avez pas toujours besoin d’une instruction Try…Catch
pour vérifier une condition susceptible de se produire. L’exemple suivant vérifie si un fichier existe avant d’essayer de l’ouvrir. Cela réduit la nécessité d’intercepter une exception levée par la méthode 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
Assurez-vous que le code dans les blocs Catch
peut correctement signaler des exceptions aux utilisateurs, qu’il s’agisse de la journalisation thread-safe ou des messages appropriés. Sinon, les exceptions peuvent rester inconnues.
Méthodes Async
Si vous marquez une méthode avec le modificateur async, vous pouvez utiliser l’opérateur await dans la méthode. Une instruction avec l’opérateur Await
interrompt l’exécution de la méthode jusqu’à ce que la tâche attendue se termine. La tâche représente un travail en cours. Lorsque la tâche associée à l’opérateur Await
est terminée, l’exécution se poursuit dans la même méthode. Pour plus d’informations, consultez Flux de contrôle dans les programmes Async.
Une tâche retournée par une méthode Async peut se terminer par un état d’erreur, indiquant qu’elle s’est terminée en raison d’une exception non gérée. Une tâche peut également se terminer par un état annulé, ce qui entraîne la levée de OperationCanceledException
de l’expression await. Pour catch l’un ou l’autre type d’exception, placez l’expression Await
associée à la tâche dans un bloc Try
bloc et catch l’exception dans le bloc Catch
. Un exemple est fourni plus loin dans cette rubrique.
Une tâche peut être dans un état d’erreur, car plusieurs exceptions ont été responsables de son erreur. Par exemple, la tâche peut être le résultat d'un appel à Task.WhenAll. Quand vous attendez une telle tâche, une seule des exceptions est interceptée et vous ne pouvez pas prévoir laquelle. Un exemple est fourni plus loin dans cette rubrique.
Une expression Await
ne peut pas se trouver à l’intérieur d’un bloc Catch
ou Finally
.
Iterators
Une fonction d’itérateur ou un accesseur Get
effectue une itération personnalisée sur une collection. Un itérateur utilise une instruction Yield pour retourner chaque élément de la collection un par un. Vous appelez une fonction d’itérateur à l’aide d’une instruction For Each...Next.
Une instruction Yield
peut se trouver à l’intérieur d’un bloc Try
. Un bloc Try
qui contient une instruction Yield
peut avoir des blocs Catch
et peut avoir un bloc Finally
. Pour obtenir un exemple, consultez Try Blocs.
Une instruction Yield
ne peut pas se trouver à l’intérieur d’un bloc Catch
ou d’un bloc Finally
.
Si le corps For Each
(en dehors de la fonction d’itérateur) lève une exception, un bloc Catch
dans la fonction d’itérateur n’est pas exécuté, mais un bloc Finally
dans la fonction d’itérateur est exécuté. Un bloc Catch
à l’intérieur d’une fonction d’itérateur intercepte uniquement les exceptions qui se produisent à l’intérieur de la fonction d’itérateur.
Situations de confiance partielle
Dans les situations de confiance partielle, par exemple une application hébergée sur un partage réseau, Try...Catch...Finally
ne catch d’exceptions de sécurité qui se produisent avant l’appel de la méthode qui contient l’appel. L’exemple suivant, lorsque vous l’avez placé sur un partage de serveur et exécuté à partir de là, génère l’erreur « System.Security.SecurityException : Request Failed ». Pour plus d’informations sur les exceptions de sécurité, consultez la classe SecurityException.
Try
Process.Start("http://www.microsoft.com")
Catch ex As Exception
Console.WriteLine("Can't load Web page" & vbCrLf & ex.Message)
End Try
Dans une telle situation de confiance partielle, vous devez placer l’instruction Process.Start
dans un Sub
distinct. L’appel initial à l’opération Sub
échoue. Cela permet à Try...Catch
de catch avant que le Sub
qui contient Process.Start
ne soit lancé et que l’exception de sécurité ne soit produite.
Exemples
Structure de Try...Catch...Finally
L'exemple ci-dessous illustre la structure de l'instruction 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
Exception dans une méthode appelée à partir d’un bloc Try
Dans l’exemple suivant, la méthode CreateException
lève un NullReferenceException
. Le code qui génère l’exception n’est pas dans un bloc Try
. Par conséquent, la méthode CreateException
ne gère pas l’exception. La méthode RunSample
gère l’exception, car l’appel à la méthode CreateException
se trouve dans un bloc Try
.
L’exemple inclut des instructions Catch
pour plusieurs types d’exceptions, classées du plus spécifique au plus général.
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
Instruction Catch When
L’exemple suivant montre comment utiliser une instruction Catch When
pour filtrer sur une expression conditionnelle. Si l’expression conditionnelle est évaluée à True
, le code dans le bloc Catch
s’exécute.
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
Instructions imbriquées Try
L’exemple suivant contient une instruction Try…Catch
contenue dans un bloc Try
. Le bloc interne Catch
lève une exception dont la propriété InnerException
est définie sur l’exception d’origine. Le bloc externe Catch
signale sa propre exception et l’exception interne.
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
Gestion des exceptions pour les méthodes asynchrones
L'exemple suivant illustre la gestion des exceptions pour les méthodes async. Pour catch une exception qui s’applique à une tâche asynchrone, l’expression Await
se trouve dans un bloc Try
de l’appelant et l’exception est interceptée dans le bloc Catch
.
Supprimez les marques de commentaire de la ligne Throw New Exception
dans l'exemple pour illustrer la gestion des exceptions. La propriété Catch
de la tâche a la valeur IsFaulted
, la propriété True
de la tâche a la valeur de l'exception et l'exception est interceptée dans le bloc Exception.InnerException
.
Supprimez les marques de commentaire de la ligne Throw New OperationCancelledException
pour montrer ce qui se passe quand vous annulez un processus asynchrone. L’exception est interceptée dans le bloc Catch
et la propriété IsCanceled
de la tâche est définie sur True
. Cependant, sous certaines conditions qui s'appliquent à cet exemple, IsFaulted
a la valeur True
et IsCanceled
a la valeur 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
Gestion de plusieurs exceptions dans les méthodes asynchrones
L’exemple suivant illustre la gestion des exceptions quand plusieurs tâches peuvent entraîner plusieurs exceptions. Le bloc Try
a l’expression Await
de la tâche retournée Task.WhenAll. La tâche est terminée quand les trois tâches auxquelles Task.WhenAll est appliqué sont terminées.
Chacune de ces trois tâches provoque une exception. Le bloc Catch
itère au sein des exceptions, qui sont trouvent dans la propriété Exception.InnerExceptions
de la tâche retournée par 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