Aller au contenu principal

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

  1. try/catch

    • Créez du code qui génère des exceptions
    • Capturez-les avec try/catch
    • Testez finally
  2. Exceptions personnalisées

    • Créez des exceptions personnalisées
    • Lancez-les dans votre code
    • Gérez-les spécifiquement
  3. using

    • Utilisez using statement
    • Comparez avec finally manuel
    • Testez la fermeture automatique
  4. Bonnes pratiques

    • Appliquez les bonnes pratiques
    • Loggez correctement
    • Messages clairs
  5. Cas pratiques

    • Créez un système de validation
    • Gèrez les erreurs de fichiers
    • Implémentez le logging

Quiz

  1. Quand s'exécute finally ?

    • Seulement en cas d'erreur
    • Toujours
    • Seulement en cas de succès
  2. Que fait using statement ?

    • Gère les exceptions
    • Ferme automatiquement les ressources
    • Optimise le code
  3. Comment créer une exception personnalisée ?

    • new Exception()
    • Créer une classe qui étend Exception
    • throw "message"
  4. Que fait throw ?

    • Gère une exception
    • Lance une exception
    • Capture une exception
  5. 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 :

  1. Exceptions personnalisées (ValidationException, FormatException)
  2. Fonctions de validation (email, age, mot de passe)
  3. Gestion complète avec try/catch
  4. Logging approprié
  5. 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.