Earn More by Sharing What You Love
Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!

Tim Corey
59m 46s
La gestion des exceptions est un aspect crucial du développement d'applications robustes. La vidéo de Tim Corey intitulée "Gestion des exceptions en C# - Quand les attraper, où les attraper et comment les attraper", fournit une explication détaillée de ce que sont les exceptions, comment les gérer et où les gérer.
Cet article vise à expliquer le traitement des exceptions en C# à l'aide de la vidéo de Tim Corey. Il s'agit d'une fonction puissante qui permet aux développeurs de gérer les erreurs et les conditions exceptionnelles qui surviennent pendant l'exécution du programme. À l'aide des blocs try, catch et finally, C# fournit un moyen structuré de gérer les erreurs d'exécution, de consigner les exceptions et de maintenir le flux du programme.
Tim commence par expliquer que de nombreux développeurs ont une vision erronée des exceptions et de leur gestion. Il souligne l'importance de comprendre ce que sont les exceptions, où et comment les gérer correctement pour créer des applications plus robustes.
Tim crée une application console dans Visual Studio 2017 pour démontrer la gestion des exceptions. Il recommande d'utiliser des applications de console pour tester de nouveaux sujets, car elles ne nécessitent qu'une configuration minimale et sont faciles à utiliser.
using System;
namespace ExceptionsDemo
{
class Program
{
static void Main(string[] args)
{
// Placeholder for input and output operations
Console.ReadLine();
}
}
}Imports System
Namespace ExceptionsDemo
Module Program
Sub Main(args As String())
' Placeholder for input and output operations
Console.ReadLine()
End Sub
End Module
End NamespaceTim ajoute une bibliothèque de classes à la solution pour simuler un scénario réel dans lequel différentes méthodes s'appellent les unes les autres.

Il supprime la classe par défaut et crée une nouvelle classe appelée DemoCode.
public class DemoCode
{
// Method to retrieve a number based on the provided position
public int GetNumber(int position)
{
int[] numbers = { 1, 4, 7, 2 };
return numbers[position];
}
// Intermediate method calls GetNumber
public int ParentMethod(int position)
{
return GetNumber(position);
}
// Top-level method calls ParentMethod
public int GrandparentMethod(int position)
{
return ParentMethod(position);
}
}Public Class DemoCode
' Method to retrieve a number based on the provided position
Public Function GetNumber(position As Integer) As Integer
Dim numbers As Integer() = {1, 4, 7, 2}
Return numbers(position)
End Function
' Intermediate method calls GetNumber
Public Function ParentMethod(position As Integer) As Integer
Return GetNumber(position)
End Function
' Top-level method calls ParentMethod
Public Function GrandparentMethod(position As Integer) As Integer
Return ParentMethod(position)
End Function
End ClassLa classe DemoCode contient des méthodes qui s'appellent les unes les autres, pour finalement récupérer un nombre dans un tableau en fonction de la position donnée.
Tim explique que l'application est destinée à démontrer les échecs plutôt que les réussites. Il introduit une exception hors limites en transmettant une position invalide à la méthode GrandparentMethod.
DemoCode demo = new DemoCode();
int result = demo.GrandparentMethod(4); // This will cause an IndexOutOfRangeException
Console.WriteLine($"The value at the given position is {result}");Dim demo As New DemoCode()
Dim result As Integer = demo.GrandparentMethod(4) ' This will cause an IndexOutOfRangeException
Console.WriteLine($"The value at the given position is {result}")L'exécution du code ci-dessus avec une position non valide entraîne une exception IndexOutOfRange. Tim montre comment le débogueur de Visual Studio met en évidence le problème et fournit des informations détaillées sur l'exception.
Tim explique une erreur courante que les développeurs commettent lorsqu'ils découvrent les blocs try-catch. Ils enveloppent souvent tout le bloc de code où ils s'attendent à ce qu'une exception se produise, ce qui peut entraîner une mauvaise gestion.
try
{
int output = 0;
output = numbers[position];
return output;
}
catch (Exception ex)
{
// Avoid returning default values that can mask the problem
return 0;
}Try
Dim output As Integer = 0
output = numbers(position)
Return output
Catch ex As Exception
' Avoid returning default values that can mask the problem
Return 0
End TryTim souligne que cette approche est problématique parce qu'elle cache l'exception et poursuit l'exécution avec des hypothèses incorrectes. Par exemple, le fait de renvoyer 0 comme valeur par défaut n'est pas forcément approprié et peut entraîner d'autres problèmes.
Tim souligne que les exceptions fournissent des informations essentielles sur les états inattendus de l'application. Si l'application reste dans cet état sans être traitée correctement, elle peut entraîner d'autres erreurs et une corruption des données.
Au lieu d'avaler les exceptions, il est essentiel de les traiter de manière appropriée. Voici une meilleure approche :
try
{
return numbers[position];
}
catch (Exception ex)
{
// Log the exception or handle it appropriately
Console.WriteLine(ex.Message);
throw; // Re-throw the exception to be handled by a higher-level handler
}Try
Return numbers(position)
Catch ex As Exception
' Log the exception or handle it appropriately
Console.WriteLine(ex.Message)
Throw ' Re-throw the exception to be handled by a higher-level handler
End TryEn relançant l'exception, vous vous assurez que le problème est propagé et qu'il peut être traité à un niveau supérieur si nécessaire.
Tim explique que si certaines exceptions peuvent être gérées de manière élégante sans planter l'application, il est important de fournir un retour d'information utile à l'utilisateur. Par exemple, l'affichage d'une boîte de message ou d'une notification avec l'option de réessayer l'opération.
Tim montre comment utiliser la propriété StackTrace de l'objet d'exception pour obtenir des informations détaillées sur l'endroit où l'exception s'est produite. La traduction doit comprendre le numéro de la classe, de la méthode et de la ligne, ce qui est très utile pour le débogage.
try
{
return numbers[position];
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
throw;
}Try
Return numbers(position)
Catch ex As Exception
Console.WriteLine(ex.StackTrace)
Throw
End TryLa propriété StackTrace fournit une trace complète de la pile d'appels, aidant les développeurs à localiser précisément le problème.
Tim explique que pour gérer correctement les exceptions, il ne suffit pas de les attraper, mais qu'il faut aussi savoir où placer les blocs try-catch. La clé est de placer les blocs try-catch à un niveau où vous avez suffisamment de contexte pour traiter l'exception de manière appropriée.
Le fait de placer un bloc try-catch au plus profond de la pile d'appels ne permet souvent pas de traiter l'exception de manière efficace, car on ne dispose pas du contexte des opérations de plus haut niveau.
// Deep level exception handling (not ideal)
try
{
return numbers[position];
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw;
}' Deep level exception handling (not ideal)
Try
Return numbers(position)
Catch ex As Exception
Console.WriteLine(ex.Message)
Throw
End TryPlacer le bloc try-catch au niveau supérieur, par exemple dans l'interface utilisateur ou le point d'entrée de l'application, permet de traiter les exceptions dans le contexte complet de l'opération.
try
{
int result = demo.GrandparentMethod(4); // This will cause an IndexOutOfRangeException
Console.WriteLine($"The value at the given position is {result}");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}Try
Dim result As Integer = demo.GrandparentMethod(4) ' This will cause an IndexOutOfRangeException
Console.WriteLine($"The value at the given position is {result}")
Catch ex As Exception
Console.WriteLine(ex.Message)
Console.WriteLine(ex.StackTrace)
End TryDe cette manière, vous pouvez fournir des messages plus informatifs à l'utilisateur et décider si l'application peut continuer à fonctionner ou si elle doit être arrêtée.
Tim met l'accent sur l'importance des informations relatives à la trace de la pile pour diagnostiquer les exceptions. La trace de pile fournit un historique détaillé des appels, montrant où l'exception s'est produite et la chaîne d'appels de méthodes qui y a conduit.
try
{
int result = demo.GrandparentMethod(4); // This will cause an IndexOutOfRangeException
Console.WriteLine($"The value at the given position is {result}");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}Try
Dim result As Integer = demo.GrandparentMethod(4) ' This will cause an IndexOutOfRangeException
Console.WriteLine($"The value at the given position is {result}")
Catch ex As Exception
Console.WriteLine(ex.Message)
Console.WriteLine(ex.StackTrace)
End TryCe résultat indique l'emplacement exact de l'exception et le chemin parcouru dans le code, ce qui facilite le débogage et la résolution du problème.
Tim montre comment traiter la logique au niveau approprié. Par exemple, si une méthode est responsable de l'ouverture et de la fermeture d'une connexion à une base de données, elle doit traiter les exceptions pour garantir une gestion correcte des ressources.
public int GrandparentMethod(int position)
{
try
{
Console.WriteLine("Open database connection");
int output = ParentMethod(position);
Console.WriteLine("Close database connection");
return output;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw; // Ensure the exception is propagated
}
}Public Function GrandparentMethod(position As Integer) As Integer
Try
Console.WriteLine("Open database connection")
Dim output As Integer = ParentMethod(position)
Console.WriteLine("Close database connection")
Return output
Catch ex As Exception
Console.WriteLine(ex.Message)
Throw ' Ensure the exception is propagated
End Try
End FunctionDans cet exemple, si une exception se produit, la connexion à la base de données n'est pas correctement fermée, ce qui peut entraîner des fuites de ressources. En ajoutant un bloc try-catch, vous pouvez vous assurer que la connexion est fermée même si une exception se produit.
Tim présente le bloc finally, qui garantit l'exécution d'un certain code, qu'une exception se produise ou non. Ceci est particulièrement utile pour le nettoyage des ressources, comme la fermeture des connexions aux bases de données.
public int GrandparentMethod(int position)
{
try
{
Console.WriteLine("Open database connection");
int output = ParentMethod(position);
return output;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw; // Re-throw the exception to ensure it's handled by a higher-level handler
}
finally
{
Console.WriteLine("Close database connection");
}
}Public Function GrandparentMethod(position As Integer) As Integer
Try
Console.WriteLine("Open database connection")
Dim output As Integer = ParentMethod(position)
Return output
Catch ex As Exception
Console.WriteLine(ex.Message)
Throw ' Re-throw the exception to ensure it's handled by a higher-level handler
Finally
Console.WriteLine("Close database connection")
End Try
End FunctionLe bloc finally s'exécute après les blocs try et catch, garantissant la fermeture de la connexion même si une exception est levée.
Tim explique l'importance de relancer les exceptions pour les faire remonter dans la pile d'appels. Cela permet aux gestionnaires de niveau supérieur de traiter les exceptions de manière appropriée.
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw; // Re-throws the exception to be handled by the calling method
}Catch ex As Exception
Console.WriteLine(ex.Message)
Throw ' Re-throws the exception to be handled by the calling method
End TryRelancer l'exception avec throw ; l'interface utilisateur garantit que l'intégralité de la trace de la pile est préservée, ce qui fournit un contexte précieux pour le débogage.
Tim montre comment les exceptions remontent dans la pile d'appels. Chaque méthode vérifie la présence d'un bloc try-catch et traite l'exception ou la transmet à l'appelant.
try
{
int result = demo.GrandparentMethod(4); // This will cause an IndexOutOfRangeException
Console.WriteLine($"The value at the given position is {result}");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}Try
Dim result As Integer = demo.GrandparentMethod(4) ' This will cause an IndexOutOfRangeException
Console.WriteLine($"The value at the given position is {result}")
Catch ex As Exception
Console.WriteLine(ex.Message)
Console.WriteLine(ex.StackTrace)
End TryDans cet exemple, la méthode GrandparentMethod attrape l'exception, l'enregistre et la relance. Le bloc try-catch de premier niveau de l'application console traite ensuite l'exception et affiche le message d'erreur et la trace de la pile.
Tim met en évidence plusieurs erreurs courantes commises par les développeurs lors de la gestion des exceptions :
Utilisant throw ex; :
Réécrire la trace de la pile et perdre un contexte précieux.
Exemple :
catch (Exception ex)
{
// Incorrect
throw ex; // Rewrites stack trace
}
Lancer une nouvelle exception :
Création d'une nouvelle exception avec un message personnalisé, mais perte de la trace de pile d'origine.
Exemple :
catch (Exception ex)
{
// Incorrect
throw new Exception("I blew up");
}
Tim explique comment créer une nouvelle exception tout en conservant la trace de la pile d'origine. Cela peut s'avérer utile lorsque vous souhaitez fournir un message d'erreur plus significatif ou un type d'exception différent, tout en conservant le contexte de l'erreur d'origine.
catch (Exception ex)
{
throw new ArgumentException("You passed in bad data", ex);
}Catch ex As Exception
Throw New ArgumentException("You passed in bad data", ex)
End CatchEn passant l'exception d'origine (ex) en tant qu'exception interne, vous conservez la trace de la pile d'origine, ce qui est crucial pour le débogage.
Tim montre comment accéder au message de l'exception originale et à la trace de la pile lors de la création d'une nouvelle exception.
catch (Exception ex)
{
Console.WriteLine("You passed in bad data");
Console.WriteLine(ex.StackTrace);
throw new ArgumentException("You passed in bad data", ex);
}Catch ex As Exception
Console.WriteLine("You passed in bad data")
Console.WriteLine(ex.StackTrace)
Throw New ArgumentException("You passed in bad data", ex)
End TryCela permet de s'assurer que l'exception remontée dans la pile contient à la fois le nouveau message et les détails de l'exception d'origine.
Tim fournit une méthode pour parcourir en boucle toutes les exceptions internes afin d'en extraire les messages et les traces de pile.
catch (Exception ex)
{
Exception inner = ex;
while (inner != null)
{
Console.WriteLine(inner.StackTrace);
inner = inner.InnerException;
}
throw;
}Catch ex As Exception
Dim inner As Exception = ex
While inner IsNot Nothing
Console.WriteLine(inner.StackTrace)
inner = inner.InnerException
End While
Throw
End TryCette boucle itère à travers chaque exception interne, en imprimant sa trace de pile, en s'assurant que toutes les couches d'exceptions sont prises en compte.
Tim explique comment gérer différents types d'exceptions en utilisant plusieurs blocs catch. Cela permet un traitement spécifique en fonction du type d'exception.
try
{
// Code that might throw an exception
}
catch (ArgumentException ex)
{
Console.WriteLine("You gave us bad information. Bad user!");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}Try
' Code that might throw an exception
Catch ex As ArgumentException
Console.WriteLine("You gave us bad information. Bad user!")
Catch ex As Exception
Console.WriteLine(ex.Message)
Console.WriteLine(ex.StackTrace)
End TryDans cet exemple, l'exception ArgumentException est gérée spécifiquement par l'impression d'un message personnalisé, tandis que toutes les autres exceptions sont traitées par un gestionnaire général qui imprime le message d'exception et la trace de la pile.

Tim insiste sur l'importance de l'ordre lors de l'utilisation de plusieurs blocs de capture. Les exceptions les plus spécifiques doivent être traitées en premier, suivies des exceptions plus générales.
try
{
// Code that might throw an exception
}
catch (ArgumentException ex)
{
Console.WriteLine("You gave us bad information. Bad user!");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}Try
' Code that might throw an exception
Catch ex As ArgumentException
Console.WriteLine("You gave us bad information. Bad user!")
Catch ex As Exception
Console.WriteLine(ex.Message)
Console.WriteLine(ex.StackTrace)
End TrySi un bloc catch plus général apparaît avant un bloc catch spécifique, il attrapera toutes les exceptions et le bloc catch spécifique ne sera jamais atteint, ce qui entraînera des erreurs de compilation.
Le guide avancé vidéo de Tim Corey sur la gestion des exceptions en C# couvre des techniques essentielles pour créer de nouvelles exceptions, préserver les traces de pile et utiliser efficacement plusieurs blocs catch. En suivant ses meilleures pratiques, les développeurs peuvent créer des applications robustes qui gèrent les exceptions avec élégance et fournissent des informations de débogage précieuses.
Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!
Join our newsletter, you’ll get exclusive access on article updates. We value your privacy