Module C#.10 – Exceptions
Objectif
Maîtriser la gestion des exceptions C# : try/catch/finally, exceptions personnalisées pour créer des applications robustes.
Théorie
try/catch/finally
Structure de base pour gérer les erreurs.
try
{
// Code qui peut générer une exception
int resultat = Diviser(10, 0);
}
catch (DivideByZeroException e)
{
// Gestion spécifique
Console.WriteLine("Division par zéro");
}
catch (Exception e)
{
// Gestion générale
Console.WriteLine($"Erreur : {e.Message}");
}
finally
{
// Code toujours exécuté
Console.WriteLine("Nettoyage");
}
Types d'exceptions
Exceptions courantes
// ArgumentException
void SetAge(int age)
{
if (age < 0)
throw new ArgumentException("Age ne peut pas être négatif", nameof(age));
}
// ArgumentNullException
void SetNom(string nom)
{
if (nom == null)
throw new ArgumentNullException(nameof(nom));
}
// IndexOutOfRangeException
int[] nombres = {1, 2, 3};
int valeur = nombres[10]; // IndexOutOfRangeException
// NullReferenceException
string? nom = null;
int longueur = nom.Length; // NullReferenceException
// FormatException
int nombre = int.Parse("abc"); // FormatException
Plusieurs catch
L'ordre est important : du plus spécifique au plus général.
try
{
// Code
}
catch (FileNotFoundException e)
{
// Spécifique
}
catch (IOException e)
{
// Plus général
}
catch (Exception e)
{
// Très général
}
finally
S'exécute toujours, même si exception lancée.
FileStream? file = null;
try
{
file = new FileStream("fichier.txt", FileMode.Open);
// Lecture
}
catch (IOException e)
{
Console.WriteLine($"Erreur : {e.Message}");
}
finally
{
file?.Close(); // Toujours fermer
}
using statement : Fermeture automatique
using (var file = new FileStream("fichier.txt", FileMode.Open))
{
// Lecture
// Fermeture automatique même en cas d'exception
}
using declaration (C# 8.0+) :
using var file = new FileStream("fichier.txt", FileMode.Open);
// Fermeture automatique à la fin du scope
Lancer des exceptions
throw
Lancer une exception.
public int Diviser(int a, int b)
{
if (b == 0)
{
throw new DivideByZeroException("Division par zéro impossible");
}
return a / b;
}
Exceptions personnalisées
Créer ses propres types d'exceptions.
Classe d'exception
class ValidationException : Exception
{
public string Champ { get; }
public ValidationException(string message, string champ)
: base(message)
{
Champ = champ;
}
}
Utilisation
void ValiderEmail(string email)
{
if (string.IsNullOrEmpty(email))
{
throw new ValidationException("Email requis", "email");
}
if (!email.Contains("@"))
{
throw new ValidationException("Email invalide", "email");
}
}
try
{
ValiderEmail("");
}
catch (ValidationException e)
{
Console.WriteLine($"Erreur de validation ({e.Champ}) : {e.Message}");
}
Propriétés des exceptions
catch (Exception e)
{
e.Message; // Message d'erreur
e.StackTrace; // Pile d'appels
e.InnerException; // Exception interne
e.Source; // Source de l'exception
e.GetType().Name; // Nom de la classe d'exception
}
Bonnes pratiques
1. Toujours gérer les exceptions
// ❌ Mauvais
public void LireFichier()
{
var contenu = File.ReadAllText("fichier.txt");
}
// ✅ Bon
public void LireFichier()
{
try
{
var contenu = File.ReadAllText("fichier.txt");
}
catch (FileNotFoundException e)
{
Console.WriteLine($"Fichier introuvable : {e.Message}");
}
catch (IOException e)
{
Console.WriteLine($"Erreur IO : {e.Message}");
}
}
2. Messages d'erreur clairs
// ❌ Mauvais
throw new Exception("Erreur");
// ✅ Bon
throw new ValidationException("L'email doit être valide", "email");
3. Logging approprié
catch (Exception e)
{
// Log pour développeur
Console.Error.WriteLine($"Erreur technique : {e.Message}");
Console.Error.WriteLine($"Stack trace : {e.StackTrace}");
// Message utilisateur clair
Console.WriteLine("Une erreur s'est produite");
}
4. Ne pas capturer Exception générique partout
// ❌ Mauvais : trop général
catch (Exception e)
{
// Cache tous les problèmes
}
// ✅ Bon : spécifique
catch (FileNotFoundException e)
{
// Gestion spécifique
}
catch (Exception e)
{
// Gestion générale en dernier recours
}
Exercice
-
try/catch
- Créez du code qui génère des exceptions
- Capturez-les avec try/catch
- Testez finally
-
Exceptions personnalisées
- Créez des exceptions personnalisées
- Lancez-les dans votre code
- Gérez-les spécifiquement
-
using
- Utilisez using statement
- Comparez avec finally manuel
- Testez la fermeture automatique
-
Bonnes pratiques
- Appliquez les bonnes pratiques
- Loggez correctement
- Messages clairs
-
Cas pratiques
- Créez un système de validation
- Gèrez les erreurs de fichiers
- Implémentez le logging
Quiz
-
Quand s'exécute finally ?
- Seulement en cas d'erreur
- Toujours
- Seulement en cas de succès
-
Que fait using statement ?
- Gère les exceptions
- Ferme automatiquement les ressources
- Optimise le code
-
Comment créer une exception personnalisée ?
- new Exception()
- Créer une classe qui étend Exception
- throw "message"
-
Que fait throw ?
- Gère une exception
- Lance une exception
- Capture une exception
-
Pourquoi ne pas capturer Exception partout ?
- C'est plus lent
- Cache les problèmes spécifiques
- C'est interdit
Mini défi
Mission : Créer un système de validation robuste
Créez un système complet de validation avec gestion d'erreurs :
Fonctionnalités :
- Exceptions personnalisées (ValidationException, FormatException)
- Fonctions de validation (email, age, mot de passe)
- Gestion complète avec try/catch
- Logging approprié
- Messages utilisateur clairs
Critères :
- ✅ Exceptions personnalisées créées
- ✅ Toutes les validations implémentées
- ✅ Gestion d'erreurs complète
- ✅ using où approprié
- ✅ Code robuste
Objectif : Maîtriser les exceptions C# et créer un système robuste.
Validation : Vous pouvez passer au module suivant quand vous maîtrisez try/catch/finally et exceptions personnalisées.