CodeGym /Cours /C# SELF /Le bloc finally et l'opérateur throw

Le bloc finally et l'opérateur throw

C# SELF
Niveau 13, Leçon 2
Disponible

1. Découverte du bloc finally

Nettoyage et libération des ressources

Imagine : tu fais des expériences dans un labo de chimie et, quand t'as fini (ou même si t'as fait péter deux-trois fioles), tu dois quand même ranger ton poste, rincer les produits et éteindre la lumière. C'est exactement à ça que sert le bloc finally — il s'exécute toujours, après try et catch, que tu aies eu une exception ou pas.


try
{
    // Ici tu mets du code "dangereux" qui peut balancer une exception
}
catch
{
    // Ici tu attrapes et gères les exceptions
}
finally
{
    // Ce code sera toujours exécuté, qu'il y ait eu une exception ou pas
}
Structure try-catch-finally en C#

Pourquoi c'est utile ? D'abord, pour être sûr de libérer les ressources : fermer un fichier, une connexion à la base de données, débloquer la porte du serveur... Sans finally, après une erreur, certaines ressources pourraient rester "bloquées" — et là, c'est la galère. Genre, le fichier reste verrouillé et même l'admin peut plus l'ouvrir.

Pourquoi pas tout mettre dans catch ?

On pourrait libérer la ressource dans catch ? Théoriquement, ouais. Mais si tout se passe bien, catch ne sera jamais exécuté. Si tu veux être sûr que la libération de la ressource se fait toujours, il te faut finally.

Dans la vraie vie, y a plein de cas où, succès ou échec, le ménage est obligatoire. C'est pour ça qu'on a inventé finally.

2. Particularités du bloc finally

Quand est-ce que finally NE s'exécute PAS ?

Question piège ! finally s'exécute toujours. Même si dans le bloc try tu fais un return (sortie anticipée de la méthode), ou si une nouvelle exception est lancée, finally sera quand même exécuté.


static void Test()
{
    try
    {
        Console.WriteLine("Avant le return");
        return;
    }
    finally
    {
        Console.WriteLine("finally va quand même s'exécuter !");
    }
}

//Appel de Test()
Test();
Va afficher :

// Avant le return
// finally va quand même s'exécuter !
    

Par contre, si ton appli se fait "tuer" violemment (genre, on coupe le courant, le process est killé ou tout le CLR crashe), le bloc finally ne sera pas exécuté. Mais là, tu peux rien y faire.

L'opérateur finally et la pile d'appels

On verra la pile d'appels plus en détail à la prochaine leçon, mais pour l'instant, retiens juste : c'est comme une pile de méthodes appelées, et le programme "descend" cette pile s'il ne trouve pas de catch adapté.

Autre point important : si une exception apparaît dans try, et qu'elle n'est pas attrapée dans catch (genre, pas de handler qui va bien), le programme quitte la méthode courante et continue à remonter la pile d'appels jusqu'à trouver un catch qui convient. Mais avant ça, le bloc finally sera exécuté à chaque niveau de la pile.

Ça garantit que les ressources sont bien libérées, même quand il y a des bugs bizarres.

3. L'opérateur throw : comment lancer soi-même des exceptions

C'est quoi throw et à quoi ça sert

Parfois, juste attraper une exception ne suffit pas — tu dois créer ta propre erreur et la "balancer" dehors. C'est exactement pour ça qu'il y a l'opérateur throw.


throw new Exception("C'est mon erreur spéciale !");
Créer et lancer sa propre exception

throw dit littéralement au CLR : « Là, j'ai vu un truc vraiment pas cool, je balance mon Exception, à toi de gérer ça si t'as appelé ce code ».

throw sans créer une nouvelle exception

Tu peux utiliser throw; dans un bloc catch pour relancer l'exception qu'on vient d'attraper — genre, t'as géré une partie du problème, mais tu veux que le code au-dessus continue à s'en occuper.


try
{
    DangerousOperation();
}
catch (Exception ex)
{
    LogError(ex);
    throw; // relance l'exception courante, la pile d'appels reste intacte
}
Relancer l'exception courante en gardant la pile d'appels

Si tu faisais throw ex;, tu perdrais les infos sur la pile d'appels — c'est pas une bonne pratique.

4. Comment finally marche avec throw ?

finally s'exécute même quand une exception est lancée

Voyons ce qui se passe si dans try on fait un throw, mais qu'on a aussi un finally :


try
{
    Console.WriteLine("Avant l'erreur...");
    throw new Exception("Erreur pendant le try !");
}
catch
{
    Console.WriteLine("Catch attrape l'erreur.");
}
finally
{
    Console.WriteLine("Finally a été exécuté.");
}
finally s'exécute même quand une exception est lancée

Résultat :


Avant l'erreur...
Catch attrape l'erreur.
Finally a été exécuté.

Et s'il n'y a pas de catch adapté, finally s'exécutera quand même avant que le programme plante.

Subtilités : que se passe-t-il si on fait throw dans finally aussi ?

Si dans finally tu fais un throw, cette exception va remplacer la précédente. Donc, les infos sur ce qui s'est passé dans try/catch seront perdues. Voilà pourquoi il vaut mieux éviter de lancer des throw dans finally si une exception a déjà eu lieu avant.


try
{
    throw new Exception("Erreur dans try");
}
finally
{
    throw new Exception("Erreur dans finally");
}
// Résultat : dehors, on verra "Erreur dans finally"
L'exception de finally remplace la précédente

5. Conseils pratiques et erreurs classiques

Ce que les débutants oublient souvent

  • Ne pas utiliser le bloc finally pour libérer les ressources, en comptant seulement sur catch.
  • Mettre du code qui peut lancer de nouvelles exceptions dans finally — ça peut causer des bugs inattendus.
  • Oublier que return dans try ne "saute pas" le finally — il sera toujours exécuté.

Alternative à finally : que choisir ?

Avec l'arrivée de la construction using (qu'on verra en détail plus tard), libérer les ressources est devenu encore plus simple, mais en vrai, using utilise sous le capot le même finally. Pour les cas un peu spéciaux (genre débloquer ou envoyer un message d'erreur) — tu dois quand même utiliser finally.

Pourquoi les recruteurs adorent finally en entretien

Tout recruteur qui a déjà codé un serveur sous grosse charge adore poser des questions sur finally. En général, ils demandent : « Que se passe-t-il si dans try il y a un return, et dans finally un throw ? » ou « Est-ce que la libération des ressources est garantie en cas d'exception ? ». Maintenant, t'as pas juste la réponse, t'as compris le truc. Tu pourras pas seulement expliquer comment marche finally, mais aussi pourquoi il est là, quand l'utiliser, et pourquoi aucun code sérieux ne s'en passe.

2
Mission
C# SELF, niveau 13, leçon 2
Bloqué
Utilisation simple du bloc finally
Utilisation simple du bloc finally
2
Mission
C# SELF, niveau 13, leçon 2
Bloqué
Relancer une exception
Relancer une exception
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION