Gestion des exceptions
Mise à jour : novembre 2007
Les règles suivantes permettent de garantir que votre bibliothèque gère les exceptions de façon appropriée.
Évitez que le code d'infrastructure ne gère des erreurs par l'interception d'exceptions non spécifiques, telles que System.Exception, System.SystemException, etc.
Vous pouvez intercepter des exceptions lorsque l'interception a pour but de lever à nouveau l'exception ou de la transférer à un autre thread. L'exemple de code suivant illustre une gestion incorrecte des exceptions.
Public Class BadExceptionHandlingExample1
Public Sub DoWork()
' Do some work that might throw exceptions.
End Sub
Public Sub MethodWithBadHandler()
Try
DoWork()
Catch e As Exception
' Handle the exception and
' continue executing.
End Try
End Sub
End Class
public class BadExceptionHandlingExample1
{
public void DoWork()
{
// Do some work that might throw exceptions.
}
public void MethodWithBadHandler()
{
try
{
DoWork();
}
catch (Exception e)
{
// Handle the exception and
// continue executing.
}
}
}
Évitez que le code de l'application ne gère des erreurs en interceptant des exceptions non spécifiques, telles que System.Exception, System.SystemException, etc. Il peut arriver parfois que la gestion d'erreurs dans des applications soit admise mais c'est rarement le cas.
Une application ne doit pas gérer des exceptions qui peuvent donner lieu à un état inattendu ou exploitable. Si vous ne pouvez pas prévoir toutes les causes possibles d'une exception et garantir que le code malveillant ne peut pas exploiter l'état de l'application qui en résulte, vous devez autoriser l'arrêt de l'application au lieu de gérer l'exception.
N'excluez pas d'exceptions spéciales lorsque vous les interceptez dans le but de les transférer.
Au lieu de créer des listes d'exceptions spéciales dans vos clauses catch, vous devez intercepter uniquement les exceptions que vous pouvez gérer de façon légitime. Les exceptions que vous ne pouvez pas gérer ne doivent pas être traitées comme des cas spéciaux dans des gestionnaires d'exceptions non spécifiques. L'exemple de code suivant illustre le test incorrect d'exceptions spéciales destinées à être à nouveau levées.
Public Class BadExceptionHandlingExample2
Public Sub DoWork()
' Do some work that might throw exceptions.
End Sub
Public Sub MethodWithBadHandler()
Try
DoWork()
Catch e As Exception
If TypeOf e Is StackOverflowException Or _
TypeOf e Is OutOfMemoryException Then
Throw
End If
End Try
End Sub
End Class
public class BadExceptionHandlingExample2
{
public void DoWork()
{
// Do some work that might throw exceptions.
}
public void MethodWithBadHandler()
{
try
{
DoWork();
}
catch (Exception e)
{
if (e is StackOverflowException ||
e is OutOfMemoryException)
throw;
// Handle the exception and
// continue executing.
}
}
}
Envisagez d'intercepter des exceptions spécifiques lorsque vous comprenez la raison de la levée de telles exceptions dans un contexte donné.
Vous devez intercepter uniquement les exceptions récupérables. Par exemple, une exception FileNotFoundException résultant d'une tentative d'ouverture d'un fichier inexistant peut être gérée par une application car elle peut communiquer le problème à l'utilisateur et permettre à ce dernier de spécifier un nom de fichier différent ou de créer le fichier. Une demande d'ouverture de fichier générant une exception ExecutionEngineException ne doit pas être gérée car vous n'avez aucune certitude quant à la cause sous-jacente de l'exception et l'application ne peut pas garantir une poursuite de l'exécution sans risque.
N'abusez pas des interceptions. Les exceptions doivent souvent être autorisées à se propager en haut de la pile des appels.
L'interception d'exceptions impossibles à gérer de façon légitime dissimule des informations de débogage critiques.
Utilisez des blocs try-finally et évitez les blocs try-catch pour le code de nettoyage. Un code d'exception correctement écrit a plus souvent recours aux blocs try-finally qu'aux blocs try-catch.
Une clause catch a pour but de vous permettre de gérer des exceptions (par exemple, en enregistrant une erreur récupérable). Quant à la clause finally, elle doit vous permettre d'exécuter du code de nettoyage, qu'une exception ait été levée ou non. Si vous allouez des ressources coûteuses ou limitées, notamment des flux ou des connexions de base de données, vous devez placer le code visant à les libérer dans un bloc finally.
Utilisez de préférence une levée d'exception vide lorsque vous interceptez et levez à nouveau une exception. C'est le meilleur moyen de conserver la pile des appels d'exception.
L'exemple de code suivant illustre une méthode capable de lever une exception. Cette méthode est référencée dans les exemples ultérieurs.
Public Sub DoWork(ByVal anObject As Object)
' Do some work that might throw exceptions.
If (anObject = Nothing) Then
Throw New ArgumentNullException("anObject", "Specify a non-null argument.")
End If
' Do work with o.
End Sub
public void DoWork(Object anObject)
{
// Do some work that might throw exceptions.
if (anObject == null)
{
throw new ArgumentNullException("anObject",
"Specify a non-null argument.");
}
// Do work with o.
}
L'exemple de code suivant illustre une exception interceptée et spécifiée de façon incorrecte lorsqu'elle est à nouveau levée. En effet, la trace de la pile désigne la nouvelle levée comme emplacement de l'erreur au lieu de pointer vers la méthode DoWork.
Public Sub MethodWithBadCatch(ByVal anObject As Object)
Try
DoWork(anObject)
Catch e As ArgumentNullException
System.Diagnostics.Debug.Write(e.Message)
' This is wrong.
Throw e
' Should be this:
' throw
End Try
End Sub
public void MethodWithBadCatch(Object anObject)
{
try
{
DoWork(anObject);
}
catch (ArgumentNullException e)
{
System.Diagnostics.Debug.Write(e.Message);
// This is wrong.
throw e;
// Should be this:
// throw;
}
}
Ne gérez pas d'exceptions non conformes à la spécification CLS (des exceptions qui ne dérivent pas de System.Exception) à l'aide d'un bloc catch sans paramètre. Les langages prenant en charge des exceptions non dérivées de System.Exception sont libres de gérer ces exceptions non conformes à CLS.
Le .NET Framework version 2.0 encapsule les exceptions non conformes à CLS dans une classe dérivée de Exception.
Portions Copyright 2005 Microsoft Corporation. Tous droits réservés.
Portions Copyright Addison-Wesley Corporation. Tous droits réservés.
Pour plus d'informations sur les règles de conception, consultez le livre « Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries » de Krzysztof Cwalina et Brad Abrams, publié par Addison-Wesley, 2005.
Voir aussi
Autres ressources
Instructions de conception pour le développement de bibliothèques de classes