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 d’instruction Catch suivantes sont les moins spécifiques et interceptent 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 est Exception, 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 :

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 n’avez pas besoin d’intercepter 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 quittez le 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 Catchexception 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 d’exceptions avec l’instruction Catch au moment de l’exécution crée une surcharge supplémentaire et est susceptible d’être plus lent 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 intercepter l’un ou l’autre type d’exception, placez l’expression Await associée à la tâche dans un bloc Try et interceptez 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, telles qu’une application hébergée sur un partage réseau, Try...Catch...Finally ne intercepte pas les 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 l’intercepter avant que le Sub qui contient Process.Start ne soit démarré et que l’exception de sécurité 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 intercepter 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

Voir aussi