Partager via


Méthodes conseillées pour la gestion des exceptions

Mise à jour : novembre 2007

Un jeu de blocs de code de gestion d'erreurs correctement conçu peut rendre un programme plus robuste et moins enclin aux blocages dus à la gestion de ces erreurs par l'application. La liste suivante contient des suggestions relatives aux meilleures pratiques pour la gestion des exceptions :

  • Déterminez quand vous devez définir un bloc try/catch. Par exemple, vous pouvez vérifier par programme la présence d'une condition qui risque probablement de se produire sans le recours à la gestion des exceptions. Dans d'autres situations, l'utilisation de la gestion des exceptions pour intercepter un cas d'erreur est appropriée.

    L'exemple suivant utilise une instruction if pour déterminer si une connexion est fermée. Vous pouvez utiliser cette méthode au lieu de lever une exception si la connexion n'est pas fermée.

       If conn.State <> ConnectionState.Closed Then
          conn.Close()
       End If
    
       if(conn.State != ConnectionState.Closed)
          conn.Close();
    

    Dans l'exemple suivant, une exception est levée si la connexion n'est pas fermée.

       Try
          conn.Close()
       Catch ex As InvalidOperationException
          'Do something with the error or ignore it.
       End Try
    
       try {
         conn.Close();
       }
       catch(InvalidOperationException ex) {
         //Do something with the error or ignore it.
       }
    

    La méthode que vous choisissez dépend de la fréquence à laquelle l'événement se produit. Si l'événement est véritablement exceptionnel et constitue une erreur (par exemple une fin de fichier inattendue), l'utilisation de la gestion des exceptions est plus indiquée car la quantité de code exécutée en situation normale est moindre. Si l'événement se produit régulièrement, l'utilisation de la méthode par programmation pour rechercher les erreurs est plus appropriée. En ce cas, si une exception se produit, la gestion de l'exception prendra plus de temps.

  • Utilisez des blocs try/finally autour du code pouvant potentiellement générer une exception et centralisez vos instructions catch en un point unique. De cette façon, l'instruction try génère l'exception, l'instruction finally ferme ou libère des ressources et l'instruction catch gère l'exception à partir d'un point central.

  • Veillez à toujours classer les exceptions dans les blocs catch de la plus spécifique à la moins spécifique. Cette technique permet de gérer l'exception spécifique avant qu'elle ne passe à un bloc catch plus général.

  • Terminez les noms de classe d'exception par le mot « Exception ». Par exemple :

    Public Class EmployeeListNotFoundException
        Inherits Exception
    
    public class MyFileNotFoundException : Exception {
    }
    
  • Lors de la création d'exceptions définies par l'utilisateur, vous devez vous assurer que les métadonnées des exceptions sont disponibles pour le code s'exécutant à distance, y compris lorsque des exceptions se produisent à travers des domaines d'application. Par exemple, supposons que le domaine d'application A crée le domaine d'application B, lequel exécute le code qui lève une exception. Pour que le domaine d'application A intercepte et gère correctement l'exception, il doit pouvoir trouver l'assembly contenant l'exception levée par le domaine d'application B. Si le domaine d'application B lève une exception qui est contenue dans un assembly sous sa base d'application, mais pas sous la base d'application du domaine d'application A, ce dernier ne peut pas trouver l'exception et le Common Language Runtime lève FileNotFoundException. Pour éviter cette situation, vous pouvez déployer l'assembly contenant les informations sur les exceptions de deux façons :

    • placez l'assembly dans une base d'application commune partagée par les deux domaines d'application

      - ou -

    • si les domaines ne partagent pas une base d'application commune, signez l'assembly contenant les informations sur les exceptions à l'aide d'un nom fort et déployez l'assembly dans le Global Assembly Cache.

  • En C# et C++, utilisez au moins les trois constructeurs communs lors de la création de vos propres classes d'exception. Pour obtenir un exemple, consultez Comment : créer des exceptions définies par l'utilisateur.

  • Dans la plupart des cas, utilisez les types d'exceptions prédéfinis. Définissez de nouveaux types d'exceptions pour des scénarios par programmation. Introduisez une nouvelle classe d'exceptions afin de permettre au programmeur d'exécuter une action différente basée sur la classe d'exceptions.

  • Pour la plupart des applications, dérivez des exceptions personnalisées à partir de la classe Exception. À l'origine, il était prévu que les exceptions personnalisées devraient dériver de la classe ApplicationException ; toutefois, en pratique, il s'est avéré que cette méthode n'apportait pas beaucoup d'avantages.

  • Insérez une chaîne de description localisée dans chaque exception. Quand l'utilisateur voit un message d'erreur, celui-ci est dérivé non pas de la classe d'exceptions mais de la chaîne de description de l'exception qui a été levée.

  • Créez des messages d'erreur corrects du point de vue de la syntaxe, y compris la ponctuation de fin. Chaque phrase de la chaîne de description d'une exception doit se terminer par un point.

  • Fournissez des propriétés Exception pour l'accès par programme. Incluez des informations supplémentaires (autres que la chaîne de description) dans une exception uniquement s'il existe un scénario par programme dans lequel les informations supplémentaires sont utiles.

  • Retournez null pour les cas d'erreur très répandus. Par exemple, une commande Open retourne null si le fichier est introuvable, mais lève une exception si le fichier est verrouillé.

  • Créez des classes de façon qu'une exception ne soit jamais levée en usage normal. Vous pouvez, par exemple, utiliser une classe FileStream pour déterminer si la fin d'un fichier a été atteinte. Vous évitez ainsi l'exception qui est levée si vous dépassez la fin du fichier pendant la lecture. L'exemple suivant montre comment lire le fichier jusqu'à la fin.

    Class FileRead
    
        Public Sub Open(ByVal fileToRead As FileStream)
    
            ' This If statement is optional
            ' as it is very unlikely that
            ' the stream would ever be null
            If IsDBNull(fileToRead) Then
                Throw New System.ArgumentNullException()
            End If
    
            Dim b As Integer
    
            ' Set the stream position to the beginning of the file.
            fileToRead.Seek(0, SeekOrigin.Begin)
    
            ' Read each byte to the end of the file.
            For i As Integer = 0 To fileToRead.Length
                b = fileToRead.ReadByte()
                Console.Write(b.ToString())
                ' Or do something else with the byte.
            Next
        End Sub
    
    End Class
    class FileRead {
        public void Open(FileStream fileToRead) 
        {
    
            // This if statement is optional
            // as it is very unlikely that
            // the stream would ever be null.
            if (fileToRead == null)
            {
                throw new System.ArgumentNullException();
            }
    
            int b;
    
            // Set the stream position to the beginning of the file.
            fileToRead.Seek(0, SeekOrigin.Begin);
    
            // Read each byte to the end of the file.
            for (int i = 0; i < fileToRead.Length; i++)
            {
                b = fileToRead.ReadByte();
                Console.Write(b.ToString());
                // Or do something else with the byte.
            }
        }
    } 
    
  • Levez InvalidOperationException si un appel de jeu de propriétés ou de méthode n'est pas approprié étant donné l'état actuel de l'objet.

  • Levez ArgumentException ou une classe dérivée de ArgumentException si des paramètres incorrects sont passés.

  • La trace de la pile commence à l'instruction où l'exception est levée et se termine à l'instruction catch qui intercepte l'exception. N'oubliez pas ce fait au moment de déterminer l'endroit auquel vous devez placer une instruction throw.

  • Utilisez des méthodes de générateur d'exceptions. Il est fréquent qu'une classe lève la même exception à partir de différents endroits de son implémentation. Pour éviter un excès de code, utilisez des méthodes d'assistance qui créent une exception et la retournent. Par exemple :

    Class File
       Private fileName As String
    
       Public Function Read(bytes As Integer) As Byte()
          If Not ReadFile(handle, bytes) Then
             Throw NewFileIOException()
          End If
       End Function 'Read
    
       Function NewFileIOException() As FileException
          Dim description As String = __unknown ' Build localized string, including fileName.
          Return New FileException(description) '
       End Function 'NewFileIOException
    End Class 'File
    
    class File {
        string fileName;
        public byte[] Read(int bytes) {
            if (!ReadFile(handle, bytes))
                throw NewFileIOException();
        }
        FileException NewFileIOException() {
            string description = // Build localized string, including fileName.
            return new FileException(description);
         }
    }
    

    Dans les autres cas, utilisez le constructeur d'exception pour générer l'exception. Cette approche est plus appropriée pour les classes d'exceptions globales, telles que ArgumentException.

  • Levez des exceptions au lieu de retourner un code d'erreur ou HRESULT.

  • Supprimez les résultats intermédiaires lorsque vous levez une exception. Les appelants doivent supposer qu'il n'y a aucun effet secondaire quand une exception est levée à partir d'une méthode.

Voir aussi

Autres ressources

Gestion et levée des exceptions