try-catch (référence C#)

L'instruction try-catch consiste en un bloc try suivi d'une ou de plusieurs clauses catch, qui désignent les gestionnaires des différentes exceptions.

Notes

Quand une exception est levée, le Common Language Runtime (CLR) recherche l'instruction catch qui gère cette exception. Si la méthode en cours d'exécution ne contient pas de bloc catch, le CLR examine la méthode qui a appelé la méthode actuelle, et ainsi de suite en remontant la pile des appels. Si aucun bloc catch n'est trouvé, le CLR affiche un message d'exception non gérée destiné à l'utilisateur et arrête l'exécution du programme.

Le bloc try contient le code protégé risquant de provoquer l'exception. Le bloc est exécuté jusqu'à la levée d'une exception ou jusqu'à sa réussite totale. Par exemple, la tentative suivante d'opérer un cast sur un objet null déclenche l'exception NullReferenceException :

object o2 = null;
try
{
    int i2 = (int)o2;   // Error
}

Bien que la clause catch puisse être employée sans arguments afin d'intercepter tout type d'exception, cette utilisation est déconseillée. En général, vous devez intercepter uniquement les exceptions que vous savez récupérer. Par conséquent, vous devez toujours spécifier un argument objet dérivé de Exception. Exemple :

catch (InvalidCastException e) 
{
}

Il est possible d'utiliser plus d'une clause catch spécifique dans la même instruction try-catch. Dans ce cas, l'ordre des clauses catch est important parce que les clauses catch sont examinées dans l'ordre. Interceptez les exceptions les plus spécifiques avant celles qui le sont le moins. Le compilateur génère une erreur si vous ordonnez vos blocs catch de sorte qu'un bloc ultérieur ne soit jamais atteint.

Une instruction throw peut être utilisée dans un bloc catch pour lever une nouvelle fois l'exception interceptée par l'instruction catch. L'exemple suivant extrait des informations source d'une exception IOException, puis lève l'exception à la méthode parente.

catch (FileNotFoundException e)
{
    // FileNotFoundExceptions are handled here.
}
catch (IOException e)
{
    // Extract some information from this exception, and then 
    // throw it to the parent method.
    if (e.Source != null)
        Console.WriteLine("IOException source: {0}", e.Source);
    throw;
}

Vous pouvez intercepter une exception et lever une exception différente. Dans ce cas, spécifiez l'exception que vous avez interceptée comme une exception interne, comme indiqué dans l'exemple suivant.

catch (InvalidCastException e) 
{
    // Perform some action here, and then throw a new exception.
    throw new YourCustomException("Put your error message here.", e);
}

Vous pouvez aussi lever à nouveau une exception lorsqu'une condition spécifiée a la valeur true, comme indiqué dans l'exemple suivant.

catch (InvalidCastException e)
{
    if (e.Data == null)
    {
        throw;
    }
    else
    {
        // Take some action.
    }
 }

Depuis un bloc try, initialisez uniquement les variables déclarées à l'intérieur. Sinon, une exception peut se produire avant la fin de l'exécution du bloc. Par exemple, dans l'exemple de code suivant, la variable n est initialisée dans le bloc try. Toute tentative d'utilisation de cette variable en dehors du bloc try dans l'instruction Write(n) générera une erreur de compilation.

static void Main() 
{
    int n;
    try 
    {
        // Do not initialize this variable here.
        n = 123;
    }
    catch
    {
    }
    // Error: Use of unassigned local variable 'n'.
    Console.Write(n);
}

Pour plus d'informations sur catch, consultez try-catch-finally.

Exceptions dans les méthodes Async

Une méthode async est marquée par un modificateur d' async et contient généralement un ou plusieurs attendent des expressions ou des instructions. Une expression d'attente implémente l'opérateur d' attendez à Task ou à Task. Une expression d' await ne peut pas apparaître dans un bloc d' catch ou un bloc d' finally .

Lorsque le contrôle atteint await dans la méthode async, la progression de la méthode est interrompue jusqu'à ce que la tâche se termine attendue. Lorsque la tâche est terminée, l'opération peut continuer dans la méthode. Pour plus d'informations, consultez Programmation asynchrone avec Async et Await (C# et Visual Basic) et Flux de contrôle dans les programmes Async (C# et Visual Basic).

La tâche achevée à laquelle await est appliqué peut être dans un état censuré en raison d'une exception non gérée dans la méthode qui retourne la tâche. Attend la tâche lève une exception. Une tâche peut également se terminer dans un état annulé si le processus asynchrone qui retourne il est annulé. En attente d'une tâche annulée lève OperationCanceledException. Pour plus d'informations sur l'annulation d'un processus asynchrone, consultez Réglage de votre application Async (C# et Visual Basic).

Pour intercepter l'exception, attendre la tâche dans un bloc d' try , et intercepter l'exception dans le bloc associé d' catch . Pour obtenir un exemple, consultez la section « exemple ».

Une tâche peut être dans un état censuré car plusieurs exceptions se sont produites dans la méthode attendue async. Par exemple, la tâche peut être le résultat d'un appel à Task.WhenAll. Lorsque vous attendez une telle tâche, une seule des exceptions est interceptée, et vous ne pouvez pas prévoir une exception est interceptée. Pour obtenir un exemple, consultez la section « exemple ».

Exemple

Dans cet exemple, le bloc try contient un appel à la méthode ProcessString qui peut provoquer une exception. La clause catch contient le gestionnaire d'exceptions qui affiche simplement un message à l'écran. Quand l'instruction throw est appelée de l'intérieur de MyMethod, le système recherche l'instruction catch et affiche le message Exception caught.

    class TryFinallyTest
{
    static void ProcessString(string s)
    {
        if (s == null)
        {
            throw new ArgumentNullException();
        }
    }

    static void Main()
    {
        string s = null; // For demonstration purposes. 

        try
        {            
            ProcessString(s);
        }

        catch (Exception e)
        {
            Console.WriteLine("{0} Exception caught.", e);
        }
    }
}
    /*
    Output:
    System.ArgumentNullException: Value cannot be null.
       at TryFinallyTest.Main() Exception caught.
     * */

Dans l'exemple suivant, deux blocs catch sont utilisés, et l'exception le plus spécifique, qui vient en premier, est interceptée.

Pour intercepter la moins exception spécifique, vous pouvez remplacer l'instruction throw dans ProcessString par l'instruction suivante : throw new Exception().

Si vous définissez le bloc catch de moindre détail d'abord dans l'exemple, le message d'erreur suivant s'affiche : A previous catch clause already catches all exceptions of this or a super type ('System.Exception').

class ThrowTest3
{
    static void ProcessString(string s)
    {
        if (s == null)
        {
            throw new ArgumentNullException();
        }
    }

    static void Main()
    {
        try
        {
            string s = null;
            ProcessString(s);
        }
        // Most specific: 
        catch (ArgumentNullException e)
        {
            Console.WriteLine("{0} First exception caught.", e);
        }
        // Least specific: 
        catch (Exception e)
        {
            Console.WriteLine("{0} Second exception caught.", e);
        }
    }
}
/*
 Output:
 System.ArgumentNullException: Value cannot be null.
 at Test.ThrowTest3.ProcessString(String s) ... First exception caught.
*/

L'exemple suivant illustre la gestion des exceptions pour les méthodes async. Pour intercepter une exception qui lève d'une tâche async, affectez l'expression d' await dans un bloc d' try , et intercepter l'exception dans un bloc d' catch .

Supprimez les marques de commentaire de la ligne de throw new Exception l'exemple pour illustrer la gestion des exceptions. La propriété d' IsFaulted de la tâche a True, la propriété d' Exception.InnerException de la tâche a pour valeur l'exception, l'exception est interceptée dans le bloc d' catch .

Supprimez les marques de commentaire de la ligne de throw new OperationCancelledException pour illustrer ce qui se produit lorsque vous processus asynchrone cancelan. La propriété d' IsCanceled de la tâche a true, et l'exception est interceptée dans le bloc d' catch . Dans certaines conditions qui ne s'appliquent pas à cet exemple, la propriété d' IsFaulted de la tâche a true et IsCanceled a la valeur false.

        public async Task DoSomethingAsync()
        {
            Task<string> theTask = DelayAsync();

            try
            {
                string result = await theTask;
                Debug.WriteLine("Result: " + result);
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Exception Message: " + ex.Message);
            }
            Debug.WriteLine("Task IsCanceled: " + theTask.IsCanceled);
            Debug.WriteLine("Task IsFaulted:  " + theTask.IsFaulted);
            if (theTask.Exception != null)
            {
                Debug.WriteLine("Task Exception Message: "
                    + theTask.Exception.Message);
                Debug.WriteLine("Task Inner Exception Message: "
                    + theTask.Exception.InnerException.Message);
            }
        }

        private async Task<string> DelayAsync()
        {
            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";
        }

        // 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 a OperationCanceledException or TaskCanceledException 
        // is thrown in the awaited method: 
        //   Exception Message: canceled 
        //   Task IsCanceled: True 
        //   Task IsFaulted:  False

L'exemple suivant illustre la gestion des exceptions lorsque plusieurs tâches peuvent entraîner de plusieurs exceptions. Le bloc d' try attend la tâche retournée par un appel à Task.WhenAll. La tâche est terminée lorsque les trois tâches auxquelles WhenAll est appliqué sont terminées.

Les trois causes de tâches une exception. Le bloc d' catch itère au sein de les exceptions, qui se trouvent dans la propriété d' Exception.InnerExceptions de la tâche qui a été retournée par Task.WhenAll.

public async Task DoMultipleAsync()
{
    Task theTask1 = ExcAsync(info: "First Task");
    Task theTask2 = ExcAsync(info: "Second Task");
    Task theTask3 = ExcAsync(info: "Third Task");

    Task allTasks = Task.WhenAll(theTask1, theTask2, theTask3);

    try
    {
        await allTasks;
    }
    catch (Exception ex)
    {
        Debug.WriteLine("Exception: " + ex.Message);
        Debug.WriteLine("Task IsFaulted: " + allTasks.IsFaulted);
        foreach (var inEx in allTasks.Exception.InnerExceptions)
        {
            Debug.WriteLine("Task Inner Exception: " + inEx.Message);
        }
    }
}

private async Task ExcAsync(string info)
{
    await Task.Delay(100);

    throw new Exception("Error-" + info);
}

// 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

Spécification du langage C#

Pour plus d'informations, voir la Spécification du langage C#. La spécification du langage est la source de référence pour la syntaxe C# et son utilisation.

Voir aussi

Tâches

Comment : lever explicitement des exceptions

Référence

Mots clés C#

Instructions try, throw et catch (C++)

Instructions de gestion des exceptions (Référence C#)

throw (référence C#)

try-finally (référence C#)

Concepts

Guide de programmation C#

Autres ressources

Référence C#