1. Introduction
Imagine que tu codes une calculatrice pour diviser deux nombres. Tout roule, jusqu’à ce que quelqu’un tente de diviser par zéro :
int a = 10;
int b = 0;
int result = a / b; // Boom !
À ce moment-là, ton programme "crashe" et l’utilisateur voit un message d’erreur flippant. Voilà ce qu’on appelle une situation exceptionnelle — un événement qui ne devrait pas arriver dans le scénario "normal" du programme et qui demande une attention particulière.
Exception — c’est un mécanisme spécial grâce auquel .NET signale à ton programme qu’il s’est passé un truc pas prévu, et que l’exécution doit être interrompue ou gérée d’une façon spéciale.
Quand une erreur d’exécution se produit (genre division par zéro, tentative d’accès à un fichier inexistant, ou — le classique — déréférencement d’un null), .NET "lance" (throw) un objet-exception spécial. Ensuite, il cherche un gestionnaire qui pourra "attraper" (catch) la situation et sait comment réagir.
Pourquoi ne pas juste retourner un "code d’erreur" ?
On pourrait retourner un code d’erreur — et plein de vieux langages (Pascal, C, et même certains API modernes) font comme ça. Mais c’est galère et risqué : on oublie facilement de vérifier le code d’erreur (on espère toujours que tout va bien) — et c’est super dur de comprendre où ça a foiré. Les exceptions permettent de centraliser la gestion des erreurs et d’y réagir de façon flexible, sans polluer ton code avec des tonnes de vérifs.
2. "Lancer" une exception
Les exceptions peuvent apparaître automatiquement — lors d’une erreur d’exécution, ou être lancées à la main avec le mot-clé throw :
int[] arr = new int[2];
arr[10] = 5; // l’exception sera lancée automatiquement System.IndexOutOfRangeException
throw new Exception("Catastrophe absolue !"); // on lance manuellement une exception Exception
Même si tu penses que ton programme est parfait, il peut toujours se passer un truc imprévu : l’utilisateur ferme un fichier, la connexion internet saute, quelqu’un coupe le courant (bon, presque).
Heureusement, .NET nous a filé non seulement le mécanisme pour "lancer" des exceptions, mais aussi des outils pour les attraper et les gérer — on va voir ça juste après.
3. Cycle de vie d’une exception : de throw à catch
Quand il se passe un truc pas cool dans le code, .NET lance une "procédure d’urgence" :
- Crée un objet exception (genre IndexOutOfRangeException).
- Le lance avec le mot-clé throw.
- Cherche un gestionnaire : il remonte la pile d’appels (du method courant à celui qui l’a appelé) — il cherche le premier bloc catch qui correspond au type de l’exception lancée.
- Si un gestionnaire est trouvé — le programme continue dans le bloc catch.
- Si aucun gestionnaire n’est trouvé — le programme plante et affiche la "stack trace" avec les détails de l’erreur.
C’est un peu comme une balle qui rebondit dans un escalier — tant qu’elle ne trouve pas de receveur, elle continue de "sauter" dans la pile.
4. Hiérarchie des exceptions dans .NET
L’arbre "parents et enfants"
Dans .NET (comme dans la plupart des langages orientés objet), les exceptions sont des classes qui héritent les unes des autres et forment toute une hiérarchie.
Elles ont toutes un ancêtre commun — la classe de base System.Exception.
System.Object
└─ System.Exception
├─ System.SystemException
│ ├─ System.NullReferenceException
│ ├─ System.IndexOutOfRangeException
│ ├─ System.DivideByZeroException
│ ├─ System.OutOfMemoryException
│ └─ ... et plein d’autres
├─ System.IO.IOException
│ ├─ System.IO.FileNotFoundException
│ ├─ System.IO.DirectoryNotFoundException
│ └─ ...
├─ System.ArgumentException
│ ├─ System.ArgumentNullException
│ └─ System.ArgumentOutOfRangeException
└─ (tes propres classes Exception)
Pourquoi des classes ?
Grâce à la hiérarchie des classes, tu peux attraper tout un "groupe" de problèmes d’un coup — par exemple, toutes les erreurs liées aux arguments de fonctions (ArgumentException et ses enfants). Et tu peux aussi créer tes propres types d’erreurs (on verra ça dans les prochaines leçons).
Les exceptions .NET les plus courantes
- NullReferenceException — tentative d’accès à une méthode ou propriété d’un objet qui vaut null. Le bon vieux pote !
- DivideByZeroException — division par zéro.
- IndexOutOfRangeException — dépassement des limites d’un tableau.
- ArgumentException, ArgumentNullException, ArgumentOutOfRangeException — paramètres de méthodes incorrects.
- FileNotFoundException, IOException — soucis lors de la gestion de fichiers.
- InvalidOperationException — opération impossible dans l’état actuel de l’objet.
- FormatException — format de données incorrect (genre essayer de convertir "abcd" en nombre).
5. Exemples : comment "explosent" différentes exceptions
Pour que ce soit plus clair, voyons des exemples de code qui déclenchent différentes exceptions.
Exemple 1 : NullReferenceException
string? str = null;
Console.WriteLine(str.Length); // Ici "Boom !" — str vaut null
Sortie :
Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.
Exemple 2 : DivideByZeroException
int a = 42;
int b = 0;
int c = a / b; // Dangereux ! Division par 0
Sortie :
Unhandled exception. System.DivideByZeroException: Attempted to divide by zero.
Exemple 3 : IndexOutOfRangeException
int[] numbers = { 1, 2, 3 };
Console.WriteLine(numbers[5]); // Pas d’élément à l’index 5
Ici, il y a clairement trop d’indices, et la sortie sera :
Unhandled exception. System.IndexOutOfRangeException: Index was outside the bounds of the array.
Exemple 4 : FileNotFoundException
using System.IO;
string content = File.ReadAllText("secret.txt");
Si tu n’as pas de fichier nommé "secret.txt", tu auras un message du genre :
Unhandled exception. System.IO.FileNotFoundException: Could not find file '/Users/zapp/RiderProjects/ConsoleApp1/ConsoleApp1/bin/Debug/net9.0/secret.txt'.
Exemple 5 : FormatException
string input = "treize";
int number = int.Parse(input); // La chaîne n’est pas un nombre
Sortie :
Unhandled exception. System.FormatException: The input string 'treize' was not in a correct format.
6. Comment utiliser tout ça ?
Comprendre comment fonctionnent les exceptions, c’est vraiment important pour tout dev. Ce n’est pas juste de la "théorie pour la théorie", c’est une compétence pratique qui impacte direct la stabilité de tes programmes. Quand tu sais gérer les erreurs correctement, ton appli ne va pas "planter" au premier bug venu, mais au contraire — elle expliquera calmement à l’utilisateur ce qui s’est passé. Ça la rend plus fiable, plus pro et carrément plus sympa à utiliser.
Et ce n’est pas qu’une question de confort. En entretien, on te demande souvent comment marche la gestion des exceptions, les types d’Exception et comment tout ça fonctionne dans .NET. Donc bien piger le sujet, c’est aussi un bonus pour trouver un taf.
En plus, tu vas croiser des exceptions tout le temps dans des vrais projets. Gestion de fichiers, réseau, bases de données, libs externes et frameworks — tout ça utilise à fond le système d’exceptions. Donc autant piger comment ça marche tout de suite, pour éviter les mauvaises surprises plus tard.
7. Erreurs classiques avec les exceptions
Erreur n°1 : ignorer complètement les exceptions.
Certains débutants (et même des devs expérimentés parfois) voient les exceptions comme un truc chiant ou inutile. Ils les ignorent, ou pire, ils mettent tout dans un catch { } et ne font rien dedans. Résultat : le programme continue "en silence" dans un état bizarre, et c’est impossible de comprendre pourquoi ça a planté.
Erreur n°2 : confondre exceptions et erreurs classiques.
On oublie souvent que toutes les erreurs ne doivent pas être gérées avec try-catch. Par exemple, si l’utilisateur entre des données invalides, il vaut mieux vérifier ça à la main, plutôt que de compter sur FormatException ou pire, utiliser les exceptions comme logique métier. Les exceptions, c’est pour les cas exceptionnels, pas pour la routine.
Erreur n°3 : mal comprendre la hiérarchie des exceptions.
Parfois, on essaie d’attraper une classe trop générale (Exception) et on chope tout, même les erreurs qu’il vaudrait mieux laisser passer. Et parfois, c’est l’inverse — on attrape des types trop précis (IndexOutOfRangeException, NullReferenceException), en oubliant qu’il peut y en avoir d’autres. Il faut bien comprendre comment est faite la hiérarchie des exceptions dans .NET et ce que tu veux vraiment gérer.
Et surtout, retiens bien : les exceptions en C# — ce n’est pas un crash ni un signal de panique, c’est juste un mécanisme pour passer à un scénario spécial d’exécution. C’est un outil puissant, si tu l’utilises bien.
GO TO FULL VERSION