devstory

Tutoriel sur la gestion des exceptions C#

  1. Qu'est-ce que Exception ?
  2. Hiérarchie des exceptions
  3. Lever des exceptions par le bloc try-catch
  4. Le bloc try-catch-finally
  5. Emballer une Exception dans une autre Exception
  6. Quelques exceptions courantes

1. Qu'est-ce que Exception ?

Tout d'abord, on voit un exemple d'illustration ci-dessus :
Dans cet exemple, il y a un extrait de code erroné à cause de la division à 0. La division par 0 évoque l'exception : DivideByZeroException
HelloException.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExceptionTutorial
{
    class HelloException
    {
        public static void Main(string[] args)
        { 
            Console.WriteLine("Three"); 
            // Cette division n'est absolument aucun problème.
            int value = 10 / 2; 
            Console.WriteLine("Two");

            // Cette division est de même
            value = 10 / 1; 
            Console.WriteLine("One"); 
            int d = 0;

            // Cette division a un problème, divisé par 0
            // Une erreur s'est produite ici.
            value = 10 / d;

            // Et le code ci-dessous ne sera pas exécuté.
            Console.WriteLine("Let's go!"); 
            Console.Read();
        }
    }
}
Le résultat de l'exécution de l'exemple :
Vous pouvez voir la notification de message d'erreur sur l'écran de la Console. La notification de message d'erreur est très claire, et elle précise quelle ligne de code s'est produite l'erreur.
Three
Two
One
Voyons le flux du programme par les illustrations ci-dessous.
  • Le programme fonctionne tout à fait normal à partir de l'étape (1), (2) à (5).
  • Dans l'étape (6), le programme est divisé par 0.
  • Le programme a été à sauter hors de la fonction principale et la ligne de code (7) n'a pas été exécutée.
Nous allons modifier le code de l'exemple ci-dessus.
HelloCatchException.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExceptionTutorial
{
    class HelloCatchException
    {
        public static void Main(string[] args)
        { 
            Console.WriteLine("Three"); 
            // Cette division n'a pas de problème.
            int value = 10 / 2;  
            Console.WriteLine("Two");

            // Cette division n'a pas de problème..
            value = 10 / 1;  
            Console.WriteLine("One");  
            int d = 0; 
            try
            {
                // Cette division a un problème, divisé par 0
                // Une erreur s'est produite ici.
                value = 10 / d;

                // Et le code ci-dessous ne sera pas exécuté.
                Console.WriteLine("Value =" + value);
            }
            catch (DivideByZeroException e)
            {
                // Le code dans le catch sera exécuté
                Console.WriteLine("Error: " + e.Message);  
                Console.WriteLine("Ignore..."); 
            } 
            // Ce code est exécuté.
            Console.WriteLine("Let's go!");  
            Console.Read();
        }
    } 
}
Et les résultats de l'exécution de l'exemple :
Three
Two
One
Error: Attempted to divide by zero.
Ignore...
Let't go!
Nous allons expliquer dans l'illustration suivante du flux de programme.
  • Les étapes (1) à (6) sont complètement normales.
  • L'exception se produit à l'étape (7), le problème étant divisé par 0.
  • Immédiatement, il saute pour exécuter la commande dans le bloc catch, l'étape (8) est ignorée.
  • L'étape (9), (10) est exécutée.
  • L'étape (11), (12) est exécutée.

2. Hiérarchie des exceptions

C'est le modèle de la carte hiérarchique d'Exception dans CSharp.
  • La classe la plus élevée est Exception
  • Deux sous-classes directes sont SystemException et AplicationException
Les Exceptions disponibles dans CSharp sont généralement dérivées (derived) de SystemException. Alors que les Exceptions des utilisateurs (programmeur) devraient hériter de ApplicationException ou de ses sous-classes.
Certaines Exceptions courantes, disponibles dans CSharp:

Type d'exception

Description

Exception

La classe de base pour toutes les exceptions.

SystemException

La classe de base pour toutes les erreurs générées lors de l'exécution.

IndexOutOfRangeException

Est jeté au moment de l'exécution lors de l'accès d'un élément de tableau avec un index incorrect.

NullReferenceException

Est jeté au moment de l'exécution lorsqu'un objet null est référencé.

AccessViolationException

Est jeté au moment de l'exécution uniquement lorsque la mémoire invalide est accessible.

InvalidOperationException

Est jeté par des méthodes lors un état non valable.

ArgumentException

La classe de base pour les exceptions sont liées à l'argument.

ArgumentNullException

Cette classe est un sous classe de ArgumentException, elle est jetée par les méthodes qui n'acceptent pas de paramètres null lors de la transmission.

ArgumentOutOfRangeException

Cette classe est un sous classe de ArgumentException, elle est jevée par la méthode lorsqu'un argument ne permet pas la transmission là-dessus.

ExternalException

La classe de base pour les exceptions se produisant ou en provenance de l'environnement extérieur.

COMException

Cette classe s'étend de ExternalException, l'exception incarne l'information de COM.

SEHException

Cette classe s'étend de ExternalException, il résume les exceptions de Win32

3. Lever des exceptions par le bloc try-catch

Nous écrivons une classe qui hérite de la classe ApplicationException.

AgeException.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExceptionTutorial
{
   class AgeException : ApplicationException
   {
       public AgeException(String message)
           : base(message)
       {
       }
   }
   class TooYoungException : AgeException
   {
       public TooYoungException(String message)
           : base(message)
       {
       }
   }
   class TooOldException : AgeException
   {
       public TooOldException(String message)
           : base(message)
       {
       }
   }
}
Et la classe AgeUtils a des méthodes statiques qui utilisent pour vérifier l'âge.
AgeUtils.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExceptionTutorial
{
    class AgeUtils
    {
        // Cette méthode prend en charge de vérifier l'âge.
        // Si l'âge est de moins de 18 ans, la méthode lève l'exception TooYoungException
        // Si l'âge est supérieur à 40, la méthode lancera une exception TooOldException
        public static void checkAge(int age)
        {
            if (age < 18)
            {
                // Si l'âge est de moins de 18 ans, une exception sera lancée
                // Cette méthode est terminée ici.
                throw new TooYoungException("Age " + age + " too young");
            }
            else if (age > 40)
            {
                // Si l'âge est supérieur à 40 ans, une exception sera lancée.
                // Cette méthode est finie ici.
                throw new TooOldException("Age " + age + " too old");
            }
            // Si l'âge se situe entre 18-40 ans.
            // Cet extrait de code sera exécuté.
            Console.WriteLine("Age " + age + " OK!");
        }
    } 
}
TryCatchDemo1.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExceptionTutorial
{
    class TryCatchDemo1
    {
        public static void Main(string[] args)
        {
            // Commencer à recruter ...
            Console.WriteLine("Start Recruiting ...");

            // Vérifier votre âge.
            Console.WriteLine("Check your Age");
            int age = 50; 
            try
            { 
                AgeUtils.checkAge(age); 
                Console.WriteLine("You pass!"); 
            }
            catch (TooYoungException e)
            {
                // ​​​​​​​
                // Annoncer d'une exception "trop jeune".
                Console.WriteLine("You are too young, not pass!");
                Console.WriteLine(e.Message); 
            }
            catch (TooOldException e)
            {
                // Annoncer d'une exception "trop vieux" ..
                Console.WriteLine("You are too old, not pass!");
                Console.WriteLine(e.Message); 
            } 
            Console.Read(); 
        }
    } 
}
Exécutez l'exemple :

Start Recruiting ...
Check your Age
You are too old, not pass!
Age 50 too old
L'exemple ci-dessous, nous allons lever les exceptions par exception au niveau supérieur. Aux niveaux plus élevés, il levera ces exceptions et tous les sous exceptions .
TryCatchDemo2.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExceptionTutorial
{
    class TryCatchDemo2
    {
        public static void Main(string[] args)
        {
            // Commencez à recruter ...
            Console.WriteLine("Start Recruiting ...");

            // Vérifiez votre âge.
            Console.WriteLine("Check your Age");
            int age = 15; 
            try
            {
                // Cet endroit peut lever (jet) TooOldException d'exception, ou TooYoungException
                AgeUtils.checkAge(age); 
                Console.WriteLine("You pass!"); 
            }
            // Si une exception survient, le type AgeException
            // Ce bloc catch sera exécuté.
            catch (AgeException e)
            { 
                Console.WriteLine("Your age invalid, you not pass");
                Console.WriteLine(e.Message); 
            } 
            Console.Read();
        }
    } 
}
Exécutez l'exemple :

Start Recruiting ...
Check your Age
Your age invalid, you not pass
Age 15 too young

4. Le bloc try-catch-finally

Ci-dessus, nous nous sommes habitués à lever des erreurs en utilisant le bloc try-catch. Le bloc try-catch-finally va gérer complètement des exceptions.
try { 
  // Faites quelque chose ici
} catch (Exception1 e) { 
  // Faites quelque chose ici
} catch (Exception2 e) { 
  // Faites quelque chose ici
} finally { 
  // Le bloc finally est toujours exécuté
  // Faites quelque chose ici
}
TryCatchFinallyDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExceptionTutorial
{
    class TryCatchFinallyDemo
    {
        public static void Main(string[] args)
        { 
            String text = "001234A2"; 
            int value = toInteger(text); 
            Console.WriteLine("Value= " + value); 
            Console.Read();  
        } 
        public static int toInteger(String text)
        {
            try
            { 
                Console.WriteLine("Begin parse text: " + text); 
                // Une exception peut lancer ici (FormatException).
                // ​​​​​​​
                int value = int.Parse(text); 
                return value; 
            }
            catch (FormatException e)
            {
                // Dans le cas de 'texte' n'est pas un numéro.
                // Ce bloc de catch sera exécuté.
                Console.WriteLine("Number format exception: " + e.Message); 
                return 0; 
            }
            finally
            { 
                Console.WriteLine("End parse text: " + text); 
            } 
        }
    } 
}
Exécutez l'exemple :
Begin parse text: 001234A2
Number format exception: Input string was not in a correct format.
End parse text: 001234A2
Value= 0
C'est le flux du programme. Enfin, le blocage finally est toujours exécuté.

5. Emballer une Exception dans une autre Exception

Nous avons besoin d'une certaine classe participées à cet exemple:
  • Person: Simule un recrutement de participants dans l'entreprise avec les informations
    • Nom, âge, sexe.
  • GenderException: Exception de genre
  • ValidateException: Exception de l'évaluation d'un candidat
  • ValidateUtils: La classe avec des méthodes statiques qui évaluent les candidats non admissibles.
    • Les normes sont les personnes âgées de 18-40
    • Et être l'homme
Person.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExceptionTutorial
{
  class Person
  {
      public static readonly string MALE = "male";
      public static readonly string FEMALE = "female";
      private string name;
      private string gender;
      private int age;
      public Person(string name, string gender, int age)
      {
          this.name = name;
          this.gender = gender;
          this.age = age;
      }
      public string GetName()
      {
          return name;
      }
      public string GetGender()
      {
          return gender;
      }
      public int GetAge()
      {
          return age;
      }
  }
}
GenderException.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExceptionTutorial
{
   class GenderException : ApplicationException
   {
       public GenderException(String message)
           : base(message)
       { 
       }
   }
}
La classe ValidateException enveloppe d'autres Exceptions.
ValidateException.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExceptionTutorial
{
    class ValidateException : ApplicationException
    { 
        // Emballe (wrap) une Exception dans une Exception.
        public ValidateException(Exception e) : base("Something invalid", e)
        { 
        }
    } 
}
ValidateUtils.java
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExceptionTutorial
{ 
    class ValidateUtils
    {
        // La méthode de contrôle un recrutement de participants.
        public static void CheckPerson(Person person)
        {
            try
            {
                // Vérifiez l'âge.
                // Valable si l'âge est entre 18-40
                // Cette méthode peut lancer TooOldException, TooYoungException.  
                AgeUtils.checkAge(person.GetAge()); 
            }
            catch (Exception e)
            {
                // Si elle n'est pas validable
                // Cette exception est emballée par ValidateException et est levée.
                throw new ValidateException(e); 
            } 
            // Si cette personne est Femme, il est invalide.
            if (person.GetGender() == Person.FEMALE)
            { 
                GenderException e = new GenderException("Do not accept women");
                throw new ValidateException(e); 
            }
        }
    } 
}
WrapperExceptionDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExceptionTutorial
{
    class WrapperExceptionDemo
    {
        public static void Main(string[] args)
        { 
            // Un candidat participe à recruter
            Person person = new Person("Marry", Person.FEMALE, 20); 
            try
            {
                // Des exceptions peuvent se produire ici.
                ValidateUtils.CheckPerson(person); 
            }
            catch (ValidateException wrap)
            { 
                // Obtenez la cause réelle
                // C'est peut-être TooYoungException, TooOldException, GenderException.
                Exception cause = wrap.GetBaseException(); 
                if (cause != null)
                {
                    Console.WriteLine("Message: " + wrap.Message);
                    Console.WriteLine("Base Exception Message: " + cause.Message);
                }
                else
                {
                    Console.WriteLine("Message: " + wrap.Message);

                }
            } 
            Console.Read();
        }
    } 
}
Exécution de l'exemple :
Age 20 OK!
Message: Something invalid
Base Exception Message: Do not accept women

6. Quelques exceptions courantes

Vous pouvez maintenant voir quelques exemples avec l'exception courante.
NullReferenceException
C'est l'une des exceptions les plus courantes et qui provoque généralement une erreur dans le programme. L'exception est relevée lorsque vous appelez la méthode ou lorsque vous accédez aux champs d'un objet qui n'a pas été initialisée (un objet null).
NullReferenceExceptionDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExceptionTutorial
{
    class NullReferenceExceptionDemo
    {
        // Par exemple, c'est une méthode qui peut renvoyer une chaîne null.
        public static string GetString()
        {
            if (1 == 2)
            {
                return "1==2 !!";
            }
            return null;
        } 
        public static void Main(string[] args)
        {
            // C'est un objet qui fait référer à un autre objet null.
            string text1 = "Hello exception";

            // Obtenez la longueur de la chaîne (string).
            int length = text1.Length; 
            Console.WriteLine("Length text1 = " + length);

            // C'est un objet qui fait référer (reference) à un autre objet null.
            String text2 = GetString(); // text2 = null.

            // Obtenez la longueur de la string.
            // NullReferenceException se produira ici.
            length = text2.Length; // ==> Runtime Error! 
            Console.WriteLine("Finish!"); 
            Console.Read();
        }
    } 
}
En réalité, comme pour gérer d'autres exceptions, vous pouvez utiliser le bloc try-catch pour lever cette exception et pour la gérer. Cependant, c'est une mécanique, normalement, nous devons vérifier afin s'assurer que l'autre objet est null avant de l'utiliser.
Vous pouvez corriger le code ci-dessus pour éviter NullReferenceException :
// Assurez-vous que 'text2' n'est pas null
String text2 = GetString(); // ==> return null

// Assurez-vous que 'text2' n'est pas null,
// Au lieu d'utiliser le bloc try-catch.
if (text2 != null)
{
      length = text2.Length;
}
IndexOutOfRangeException
Cette exception se produit lorsque vous essayez d'accéder à l'élément dont l'index est invalide dans le tableau. Par exemple, un tableau comporte 10 éléments, mais vous accédez à l'élément avec l'index 20.
IndexOutOfRangeExceptionDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExceptionTutorial
{
    class IndexOutOfRangeExceptionDemo
    {
        public static void Main(string[] args)
        { 
            String[] strs = new String[] { "One", "Two", "Three" }; 
            // Accédez à l'élément à l'index 0.
            String str1 = strs[0]; 
            Console.WriteLine("String at 0 = " + str1);

            // Accédez à l'élément à l'index 5.
            // IndexOutOfRangeException se produira ici.
            String str2 = strs[5]; 
            Console.WriteLine("String at 5 = " + str2); 
            Console.Read(); 
        }
    }
}
Afin d'éviter IndexOutOfRangeException vous vérifiez le tableau au lieu d'utiliser le bloc try-catch.
if (strs.length > 5)
{
     String str2 = strs[5];
     Console.WriteLine("String at 5 = " + str2);
}
else
{
     Console.WriteLine("No elements with index 5");
}