Exercice - Intercepter des types d’exceptions spécifiques
Plus haut dans ce module, vous avez appris que les objets d’exception interceptés par votre application C# sont des instances d’une classe d’exception. En règle générale, votre code effectuera un catch sur l’un des éléments suivants :
- Objet d’exception qui est une instance de la
System.Exceptionclasse de base. - Objet d’exception qui est une instance d’un type d’exception qui hérite de la classe de base. Par exemple, une instance de la
InvalidCastExceptionclasse.
Examiner les propriétés d’exception
System.Exception est la classe de base dont héritent tous les types d’exceptions dérivés. Chaque type d’exception hérite de la classe de base via une hiérarchie de classes spécifique. Par exemple, la hiérarchie de classes pour la InvalidCastException classe est la suivante :
Object
Exception
SystemException
InvalidCastException
La plupart des classes d'exception qui héritent de Exception n'ajoutent pas de fonctionnalités supplémentaires ; elles se contentent simplement d’hériter de Exception. Par conséquent, l’examen des propriétés de la Exception classe vous permet de comprendre la plupart des exceptions et comment vous pouvez utiliser une exception dans votre code.
Voici les propriétés de la Exception classe :
- Données : la
Datapropriété contient des données arbitraires dans des paires clé-valeur. - HelpLink : la
HelpLinkpropriété peut être utilisée pour contenir une URL (ou URN) vers un fichier d’aide qui fournit des informations détaillées sur la cause d’une exception. - HResult : La
HResultpropriété peut être utilisée pour accéder à une valeur numérique codée affectée à une exception spécifique. - InnerException : la
InnerExceptionpropriété peut être utilisée pour créer et conserver une série d’exceptions pendant la gestion des exceptions. - Message : la
Messagepropriété fournit des détails sur la cause d’une exception. - Source : La
Sourcepropriété peut être utilisée pour accéder au nom de l’application ou à l’objet qui provoque l’erreur. - StackTrace : la
StackTracepropriété contient une trace de pile qui peut être utilisée pour déterminer où une erreur s’est produite. - TargetSite : la
TargetSitepropriété peut être utilisée pour obtenir la méthode qui lève l’exception actuelle.
C’est correct si vous vous sentez un peu submergé par cet examen des propriétés d’exception, des classes de base et de l’héritage. Ne vous inquiétez pas, l’interception des exceptions dans votre code et l’accès aux propriétés d’une exception sont plus faciles que d’expliquer le fonctionnement des exceptions et des propriétés d’exception.
Remarque
Dans ce module, vous allez vous concentrer sur l’utilisation de la propriété de message d’une exception pour signaler l’exception dans l’interface utilisateur de votre application.
Accéder aux propriétés d’un objet d’exception
Maintenant que vous comprenez les objets d’exception et leurs propriétés, il est temps de commencer à coder.
Mettez à jour votre fichier Program.cs comme suit :
try { Process1(); } catch { Console.WriteLine("An exception has occurred"); } Console.WriteLine("Exit program"); static void Process1() { try { WriteMessage(); } catch { Console.WriteLine("Exception caught in Process1"); } } static void WriteMessage() { double float1 = 3000.0; double float2 = 0.0; int number1 = 3000; int number2 = 0; Console.WriteLine(float1 / float2); Console.WriteLine(number1 / number2); }Prenez le temps de passer le code en revue.
Il s’agit du même code que celui que vous avez vu dans l’unité précédente (le code de solution pour l’activité de défi). Vous savez qu’une exception est levée pendant la méthode
WriteMessage. Vous savez également que l’exception est interceptée dans la méthodeProcess1. Vous utiliserez ce code pour examiner les objets d’exception et les types d’exceptions spécifiques.Mettez à jour la méthode
Process1comme ceci :static void Process1() { try { WriteMessage(); } catch (Exception ex) { Console.WriteLine($"Exception caught in Process1: {ex.Message}"); } }Prenez une minute pour examiner vos mises à jour.
Notez que votre clause mise à jour
catchintercepte une instance de laExceptionclasse dans un objet nomméex. Notez également que votreConsole.WriteLine()méthode utiliseexpour accéder à la propriété de l’objetMessageet afficher le message d’erreur dans la console.Bien que la
catchclause puisse être utilisée sans arguments, cette approche n’est pas recommandée. Si vous ne spécifiez pas d’argument, tous les types d’exceptions sont interceptés et vous ne pouvez pas les discerner.En règle générale, vous ne devez intercepter que les exceptions à partir de lesquelles votre code sait comment récupérer. Par conséquent, votre
catchclause doit spécifier un argument d’objet dérivé deSystem.Exception. Le type d’exception doit être aussi spécifique que possible. Cela permet d’éviter d’intercepter les exceptions que votre gestionnaire d’exceptions n’est pas en mesure de résoudre. Vous allez mettre à jour votre code pour intercepter un type d’exception spécifique plus loin dans cet exercice.Dans le menu Fichier , sélectionnez Enregistrer.
Définissez le point d’arrêt sur la ligne de code suivante :
Console.WriteLine($"Exception caught in Process1: {ex.Message}");Dans le menu Exécuter , sélectionnez Démarrer le débogage
L’exécution du code doit s’interrompre au point d’arrêt.
Placez le curseur de la souris sur
ex.Notez que IntelliSense affiche les mêmes propriétés d’exception que celles que vous avez examinées précédemment.
Prenez une minute pour examiner les informations décrivant l’objet
exd’exception.Notez que l’exception est un type d’exception
System.DivideByZeroExceptionet que laMessagepropriété est définie surAttempted to divide by zero..Notez que la
StackTracepropriété signale la méthode et le numéro de ligne où l’erreur s’est produite, ainsi que la séquence d’appels de méthode (et numéros de ligne) qui ont conduit à l’erreur.Dans la barre d’outils Déboguer, sélectionnez Continuer.
Prenez une minute pour examiner la sortie de la console.
Notez que la propriété de
Messagel’exception est incluse dans la sortie générée par votre application :∞ Exception caught in Process1: Attempted to divide by zero. Exit program
Intercepter un type d’exception spécifique
Maintenant que vous connaissez le type d’exception à intercepter, vous pouvez mettre à jour votre catch clause pour gérer ce type d’exception spécifique.
Mettez à jour la méthode
Process1comme ceci :static void Process1() { try { WriteMessage(); } catch (DivideByZeroException ex) { Console.WriteLine($"Exception caught in Process1: {ex.Message}"); } }Enregistrez votre code, puis démarrez une session de débogage.
Notez que votre application mise à jour signale les mêmes messages à la console.
Bien que les messages signalés soient identiques, il existe une différence importante. Votre
Process1méthode intercepte uniquement les exceptions du type spécifique qu’elle est prête à gérer.Pour générer un autre type d’exception, mettez à jour la
WriteMessageméthode comme suit :static void WriteMessage() { double float1 = 3000.0; double float2 = 0.0; int number1 = 3000; int number2 = 0; byte smallNumber; Console.WriteLine(float1 / float2); // Console.WriteLine(number1 / number2); checked { smallNumber = (byte)number1; } }Notez l’utilisation de l’instruction
checked.Lorsque vous effectuez des calculs de type intégral qui attribuent la valeur d’un type intégral à un autre type intégral, le résultat dépend du contexte de vérification de dépassement de capacité. Dans un
checkedcontexte, la conversion réussit si la valeur source se trouve dans la plage du type de destination. Sinon, une exceptionOverflowExceptionest levée. Dans un contexte non vérifié, la conversion réussit toujours et se poursuit comme suit :Si le type source est supérieur au type de destination, la valeur source est tronquée en ignorant ses bits « supplémentaires » les plus significatifs. Le résultat est ensuite traité comme une valeur du type de destination.
Si le type source est plus petit que le type de destination, la valeur source est étendue par signe ou étendue zéro afin qu’elle soit de la même taille que le type de destination. L’extension de signe est utilisée si le type source est signé ; l’extension à zéro est utilisée si le type source est non signé. Le résultat est ensuite traité comme une valeur du type de destination.
Si le type source est de la même taille que le type de destination, la valeur source est traitée comme une valeur du type de destination.
Remarque
Les calculs de type intégral qui ne sont pas à l’intérieur d’un
checkedbloc de code sont traités comme s’ils se trouvent à l’intérieur d’ununcheckedbloc de code.Enregistrez votre code, puis démarrez une session de débogage.
Notez qu’un nouveau type d’exception est intercepté par la
catchclause dans les instructions de niveau supérieur plutôt qu’à l’intérieur de laProcess1méthode.Votre application imprime les messages suivants dans la console :
∞ An exception has occurred Exit programRemarque
Le
catchbloc dansProcess1n’est pas exécuté. Il s’agit du comportement souhaité. Interceptez uniquement les exceptions que votre code est prêt à gérer.
Intercepter plusieurs exceptions dans un bloc de code
À ce stade, vous vous demandez peut-être ce qui se passe quand plusieurs exceptions se produisent dans un bloc de code unique. Votre code catch gérera-t-il chaque exception au fur et à mesure qu’elles se produisent ?
Mettez à jour la méthode
WriteMessagecomme ceci :static void WriteMessage() { double float1 = 3000.0; double float2 = 0.0; int number1 = 3000; int number2 = 0; byte smallNumber; Console.WriteLine(float1 / float2); Console.WriteLine(number1 / number2); checked { smallNumber = (byte)number1; } }Définissez le point d’arrêt à l’intérieur de la
WriteMessage()méthode sur la ligne de code suivante :Console.WriteLine(float1 / float2);Enregistrez votre code, puis démarrez une session de débogage.
Parcourez votre code une ligne à la fois et notez ce qui se passe après que votre code gère la première exception.
Lorsque la première exception se produit, le contrôle est passé à la première
catchclause qui peut gérer l’exception. Le code qui générerait la deuxième exception n’est jamais atteint. Cela signifie que certains de votre code ne sont jamais exécutés. Cela pourrait entraîner des problèmes sérieux.Prenez une minute pour prendre en compte la façon dont vous pouvez gérer plusieurs exceptions et quand/pourquoi vous ne souhaiterez peut-être pas que votre code gère plusieurs exceptions.
Vous avez appris précédemment dans ce module que les exceptions doivent être interceptées aussi près de l’endroit où elles se produisent que possible. Dans cet esprit, vous pouvez choisir de mettre à jour la méthode
WriteMessagepour intercepter des exceptions à l’aide de son propretry-catch. Par exemple:static void WriteMessage() { double float1 = 3000.0; double float2 = 0.0; int number1 = 3000; int number2 = 0; byte smallNumber; try { Console.WriteLine(float1 / float2); Console.WriteLine(number1 / number2); } catch (DivideByZeroException ex) { Console.WriteLine($"Exception caught in WriteMessage: {ex.Message}"); } checked { smallNumber = (byte)number1; } }Vous pouvez également encapsuler le code qui provoque le
OverflowExceptiondans untry-catchdistinct à l'intérieur de la méthodeWriteMessage().checked { try { smallNumber = (byte)number1; } catch (OverflowException ex) { Console.WriteLine($"Exception caught in WriteMessage: {ex.Message}"); } }Dans quelles conditions ne serait-il pas souhaitable d’intercepter les exceptions suivantes ?
Considérez le cas lorsque votre méthode (ou bloc de code) termine un processus en deux parties. Supposons que la deuxième partie du processus dépend de la première partie terminée. Si la première partie du processus ne peut pas se terminer correctement, il n’y a aucun point à passer à la deuxième partie du processus. Dans ce cas, il est souvent préférable de présenter à l’utilisateur un message expliquant la condition d’erreur sans tenter la partie ou les parties restantes du processus plus volumineux.
Intercepter des types d’exceptions distincts dans un bloc de code
Il existe des moments où des variations de vos données peuvent entraîner différents types d’exceptions.
Effacez vos points d’arrêt, puis remplacez le contenu de votre fichier Program.cs par le code suivant :
// inputValues is used to store numeric values entered by a user string[] inputValues = new string[]{"three", "9999999999", "0", "2" }; foreach (string inputValue in inputValues) { int numValue = 0; try { numValue = int.Parse(inputValue); } catch (FormatException) { Console.WriteLine("Invalid readResult. Please enter a valid number."); } catch (OverflowException) { Console.WriteLine("The number you entered is too large or too small."); } catch(Exception ex) { Console.WriteLine(ex.Message); } }Prenez une minute pour passer en revue ce code.
Tout d’abord, le code crée un tableau de chaînes nommé
inputValues. Les données du tableau sont destinées à représenter les valeurs d’entrée entrées par un utilisateur qui a été invité à entrer des valeurs numériques. Selon la valeur entrée, différents types d’exceptions peuvent se produire.Notez que le code utilise la
int.Parseméthode pour convertir les valeurs de chaîne « input » en entiers. Leint.Parsecode est placé à l’intérieur d’untrybloc de code.Définissez un point d’arrêt sur la ligne de code suivante :
int numValue = 0;Enregistrez votre code, puis démarrez une session de débogage.
Parcourez le code une ligne à la fois et notez que différents types d’exceptions sont interceptés.
Récapitulatif
Voici quelques points importants à retenir de cette unité :
- La
catchclause doit être configurée pour intercepter un type d’exception spécifique. Par exemple, le type d’exceptionDivideByZeroException. - Les propriétés d’un objet d’exception sont accessibles dans le
catchbloc. Par exemple, vous pouvez utiliser laMessagepropriété pour informer l’utilisateur de l’application d’un problème. - Vous pouvez spécifier deux clauses ou plus
catchlorsque vous devez intercepter plusieurs types d’exception.