Meilleures pratiques pour gérer les exceptions en C #

La gestion des exceptions est la technique de gestion des erreurs d'exécution dans le code de votre application. Fondamentalement, vous avez deux catégories d'exceptions: les exceptions générées par l'application et celles générées par le runtime. Les exceptions doivent être traitées avec précaution - vous devez avoir une bonne idée de la manière dont les exceptions doivent être traitées et du moment où elles doivent être traitées dans votre code. Dans cet article, je présenterai quelques conseils et bonnes pratiques pour travailler avec des exceptions en C #.

La classe de base pour toutes les exceptions dans .NET est Exception. Toutes les classes d'exceptions de la hiérarchie d'exceptions dérivent directement ou indirectement de cette classe. Les classes ApplicationException et SystemException sont dérivées de la classe Exception. Le Common Language Runtime (CLR) lève une instance d'un type dérivé de SystemException lorsqu'une erreur se produit au moment de l'exécution. Notez que vous ne devez jamais intercepter SystemException ou lancer une instance de SystemException dans le code de votre application.

Lors de la création de classes d'exception personnalisées, dérivez toujours de la classe Exception et non de la classe ApplicationException. L'une des raisons à cela est qu'une instance d'ApplicationException est levée par l'application et jamais par le runtime. En lançant une instance d'ApplicationException dans votre code, vous augmenteriez simplement la pile d'appels sans ajouter beaucoup de valeur.

Utiliser la gestion des exceptions pour renvoyer des informations à partir d'une méthode est une mauvaise approche de conception. Si vous renvoyez des données d'exception à partir de votre méthode, la conception de votre classe est erronée et doit être revue. Notez que les exceptions sont remontées au niveau supérieur dans la hiérarchie des appels de méthode et il n'est pas recommandé de gérer les exceptions dans toutes les couches de votre application. Vous devez gérer une exception aussi haut que possible dans la hiérarchie des appels - vous pouvez utiliser une exception dans la couche de présentation et afficher les messages appropriés à l'utilisateur pour notifier l'erreur exacte qui s'est produite.

La relance d'une exception est nécessaire lorsque vous souhaitez annuler une transaction de base de données. Il est recommandé d'utiliser des exceptions spécifiques telles que FileNotFoundException, IOException, etc. lors de l'écriture de gestionnaires d'exceptions, puis un bloc catch général à la fin avec la classe Exception. Cela garantirait que vous apprenez à connaître l'erreur exacte ou l'erreur spécifique qui s'est produite. Le MSDN déclare: "La classe ApplicationException ne fournit pas d'informations sur la cause des exceptions. Dans la plupart des scénarios, les instances de cette classe ne doivent pas être levées. Dans les cas où cette classe est instanciée, un message lisible par l'homme décrivant l'erreur doit être transmis au constructeur. "

Vous devez utiliser des blocs try - catch pour gérer les exceptions et utiliser un bloc finally pour nettoyer les ressources utilisées dans votre programme. Le bloc try contiendrait du code qui pourrait déclencher une exception, le bloc catch sera utilisé pour gérer l'exception lancée à l'intérieur du bloc try et le bloc finally sera utilisé pour désallouer toutes les ressources utilisées par le programme. Notez que l'exécution du bloc finally est garantie indépendamment du fait qu'une exception s'est produite ou non. Par conséquent, le bloc final est le meilleur endroit dans votre code pour nettoyer les ressources utilisées par votre programme.

L'extrait de code ci-dessous montre comment l'instruction "using" peut être utilisée pour supprimer des ressources. Notez que l 'instruction «using» est un équivalent du bloc try - finally.

public string Read(string fileName)

{

try

{

string data;

using (StreamReader streamReader = new StreamReader(fileName))

{

data = streamReader.ReadToEnd();

}

return data;

}

catch (Exception)

{

throw;

}

}

Lancer des exceptions coûte cher. C'est une mauvaise pratique de renvoyer les exceptions - en renvoyant des exceptions, vous perdriez la trace de la pile.

try

{

//Some code that might throw an exception

}

catch(Exception ex)

{

throw ex;

}

À la place, utilisez simplement l'instruction "throw" si vous ne souhaitez pas gérer l'exception dans votre gestionnaire d'exceptions et propager l'exception vers le haut dans la hiérarchie des appels.

try

{

//Some code that might throw an exception

}

catch(Exception ex)

{

throw;

}

Ne jamais avaler les exceptions - vous ne devez jamais cacher l'erreur qui s'est produite. Il est recommandé de consigner les exceptions dans votre application. Lors de la journalisation des exceptions, vous devez toujours journaliser l'instance d'exception afin que la trace complète de la pile soit enregistrée et non le message d'exception uniquement. Voici un exemple qui illustre cela.

try

{

//Some code that might throw an exception

}

catch(Exception ex)

{

LogManager.Log(ex.ToString());

}

Vous ne devez jamais utiliser d'exceptions pour propager ou exécuter des règles métier dans votre application. Vous pouvez éviter les exceptions dans votre code en utilisant une logique de validation appropriée. Les exceptions doivent dans la plupart des cas être évitées - vous ne devez l'utiliser que lorsque cela est nécessaire.

Vous pouvez consulter cet article MSDN pour plus d'informations.