Rappelez-vous de ce code :
Code : C# | string chaine = "dix";
int valeur = Convert.ToInt32(chaine);
|
Si nous l’exécutons, nous aurons l’erreur suivante :
L’application nous affiche un message d’erreur et l’application « plante » lamentablement produisant un rapport d’erreur.
Ce qu’il se passe en fait, c’est que lors de la conversion, si le framework .NET n’arrive pas à convertir correctement la chaine de caractères en entier,
il lève une exception. Cela veut dire qu’il informe le programme qu’il rencontre un cas limite qui nécessite d’être géré.
Si ce cas limite n’est pas géré, alors l’application plante et c’est le CLR qui intercepte l’erreur et qui fait produire un rapport au système d’exploitation.
Pourquoi une exception et pas un message d’erreur ?
L’intérêt des exceptions est qu'elles sont typées. Finis les codes d’erreurs incompréhensibles. C’est le type de l’exception, c'est-à-dire sa classe, qui va nous permettre d’identifier le problème.
Pour éviter le plantage de l’application, nous devons gérer ces cas limites et intercepter les exceptions.
Pour ce faire, il faut encadrer les instructions pouvant atteindre des cas limites avec le bloc d’instruction
try…catch, par exemple :
Code : C# | try
{
string chaine = "dix";
int valeur = Convert.ToInt32(chaine);
Console.WriteLine("Ce code ne sera jamais affiché");
}
catch (Exception)
{
Console.WriteLine("Une erreur s'est produite dans la tentative de conversion");
}
|
Si nous exécutons ce bout de code, l’application ne plantera plus et affichera qu’une erreur s’est produite…
Nous avons « attrapé » l’exception levée par la méthode de conversion grâce au mot-clé
catch.
Cette construction nous permet de surveiller l’exécution d’un bout de code, situé dans le bloc
try et s’il y a une erreur, alors nous interrompons son exécution pour traiter l’erreur en allant dans le bloc
catch.
La suite du code dans le
try, à savoir l’affichage de la ligne avec
Console.WriteLine, ne sera jamais exécuté car lorsque la conversion échoue, il saute directement au bloc
catch.
Inversement, il est possible de ne jamais passer dans le bloc
catch si les instructions ne provoquent pas d’erreur :
Code : C# | try
{
string chaine = "10";
int valeur = Convert.ToInt32(chaine);
Console.WriteLine("Conversion OK");
}
catch (Exception)
{
Console.WriteLine("Nous ne passons jamais ici ...");
}
|
Ainsi le code ci-dessus affichera bien uniquement que la conversion est bonne. Et en toute logique, il ne passera pas dans le bloc de traitement d’erreur, car il n’y en a pas eu.
Il est possible d’obtenir des informations sur l’exception en utilisant un paramètre dans le bloc
catch :
Code : C# 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | try
{
string chaine = "dix";
int valeur = Convert.ToInt32(chaine);
}
catch (Exception ex)
{
Console.WriteLine("Il y a un eu une erreur, plus d'informations ci-dessous :");
Console.WriteLine();
Console.WriteLine("Message d'erreur : " + ex.Message);
Console.WriteLine();
Console.WriteLine("Pile d'appel : " + ex.StackTrace);
Console.WriteLine();
Console.WriteLine("Type de l'exception : " + ex.GetType());
}
|
Ici, nous affichons le message d’erreur, la pile d’appel et le type de l’exception, ce qui donne :
D’une manière générale, la méthode
ToString() de l’exception fournit des informations suffisantes pour identifier l’erreur :
Code : C# | try
{
string chaine = "dix";
int valeur = Convert.ToInt32(chaine);
}
catch (Exception ex)
{
Console.WriteLine("Il y a un eu une erreur : " + ex.ToString());
}
|
Ce qui donne :
Les exceptions peuvent être de beaucoup de formes. Ici nous remarquons que l’exception est de type
System.FormatException. Cette exception est utilisée en général lorsque le format d’un paramètre ne correspond pas à ce qui est attendu. En l’occurrence ici nous attendons un paramètre de type chaine de caractères qui représente un entier.
C’est une exception spécifique qui est dédiée à un type d’erreur précis.
Il faut savoir que comme beaucoup d’autres objets du framework .NET, les exceptions spécifiques dérivent d’une classe de base, à savoir la classe
Exception. Il existe une hiérarchie entre les exceptions. Globalement, deux grandes familles d’exceptions existent :
ApplicationException et
SystemException. Elles dérivent toutes les deux de la classe de base
Exception. La première est utilisée lorsque des erreurs récupérables sur des applications apparaissent, la seconde est utilisée pour toutes les exceptions générées par le framework .NET.
Par exemple, l’exception que nous avons vue,
FormatException dérive directement de
SystemException qui dérive elle-même de la classe
Exception.
Le framework .NET dispose de beaucoup d’exceptions correspondant à beaucoup de situations. Notons encore au passage une autre exception bien connue des développeurs qui est la
NullReferenceException. Elle se produit lorsqu’on essaie d’accéder à un objet qui vaut
null. Par exemple :
Code : C# | Voiture voiture = null;
voiture.Vitesse = 10;
|
Vous aurez remarqué que dans la construction suivante :
Code : C# | try
{
string chaine = "dix";
int valeur = Convert.ToInt32(chaine);
}
catch (Exception ex)
{
Console.WriteLine("Il y a un eu une erreur : " + ex.ToString());
}
|
nous voyons que le bloc
catch prend en paramètre la classe de base
Exception.
Cela veut dire que nous souhaitons intercepter toutes les exceptions qui dérivent de
Exception ; c’est-à-dire en fait toutes les exceptions, car pour avoir une exception, elle doit forcément dériver de la classe
Exception.
C’est utile lorsque nous voulons attraper toutes les exceptions. Mais savons-nous forcément quoi faire dans le cas de toutes les erreurs ?
Il est possible d’être plus précis afin de n’attraper qu’un seul type d’exception. Il suffit de préciser le type de l’exception attendu comme paramètre du
catch.
Par exemple le code suivant nous permet d’intercepter toutes les exceptions du type
FormatException :
Code : C# | try
{
string chaine = "dix";
int valeur = Convert.ToInt32(chaine);
}
catch (FormatException ex)
{
Console.WriteLine(ex);
}
|
Cela veut par contre dire que si nous avons une autre exception à ce moment-là, du style
NullReferenceException, l’exception ne sera pas attrapée. Ce qui fait que le code suivant va planter :
Code : C# | try
{
Voiture v = null;
v.Vitesse = 10;
}
catch (FormatException ex)
{
Console.WriteLine("Erreur de format : " + ex);
}
|
En effet, nous demandons la surveillance de l’exception
FormatException uniquement. Ainsi, l’exception
NullReferenceException ne sera pas attrapée.