Partager via


CA2000 : Supprimez les objets avant d'être hors de portée

TypeName

DisposeObjectsBeforeLosingScope

CheckId

CA2000

Catégorie

Microsoft.Reliability

Modification avec rupture

Modification sans rupture

Cause

Un objet local d'un type IDisposable est créé, mais n'est pas supprimé avant que toutes les références à celui-ci se trouvent hors de portée.

Description de la règle

Si un objet qui peut être supprimé ne l'est pas explicitement avant que toutes les références à celui-ci se trouvent hors de portée, il est supprimé à un moment indéterminé, lorsque le garbage collector exécute le finaliseur de l'objet. Sachant qu'un événement exceptionnel peut se produire et empêcher l'exécution du finaliseur de l'objet, ce dernier doit plutôt être supprimé explicitement.

Comment corriger les violations

Pour corriger une violation de cette règle, appelez Dispose sur l'objet avant que toutes les références à ce dernier ne se trouvent hors de portée.

Notez que vous pouvez utiliser l'instruction using (Using en Visual Basic) pour inclure dans un wrapper les objets qui implémentent IDisposable. Les objets inclus dans un wrapper de cette manière seront supprimés automatiquement à la fin du bloc using.

Dans les situations suivantes, l'instruction using n'est pas suffisante pour protéger des objets IDisposable et peut provoquer le déclenchement de CA2000.

  • Le retour d'un objet jetable requiert que l'objet soit construit dans un bloc try/finally en dehors d'un bloc using.

  • L'initialisation des membres d'un objet jetable ne doit pas être faite dans le constructeur d'une instruction using.

  • Constructeurs d'imbrication qui sont protégés uniquement par un gestionnaire d'exceptions. Par exemple :

    using (StreamReader sr = new StreamReader(new FileStream("C:\myfile.txt", FileMode.Create)))
    { ... }
    

    provoque le déclenchement du CA2000 parce qu'un échec dans la construction de l'objet StreamReader peut empêcher la fermeture de l'objet FileStream.

  • Les objets dynamiques doivent utiliser un objet shadow pour implémenter le modèle Dispose des objets IDisposable.

Quand supprimer les avertissements

Ne supprimez pas d'avertissement de cette règle, à moins que vous ayez appelé une méthode sur votre objet qui appelle Dispose, tel que Close.

Règles connexes

CA2213 : Les champs pouvant être supprimés doivent l'être

CA2202 : Ne pas supprimer des objets plusieurs fois

Exemple

Si vous implémentez une méthode qui rétablit un objet jetable, utilisez un bloc try/finally sans un bloc catch pour s'assurer que l'objet est jeté. En utilisant un bloc try-finally, vous permettez aux exceptions d'être levées et garantissez la suppression de l'objet.

Dans la méthode OpenPort1, l'appel pour ouvrir l'objet ISerializable SerialPort ou l'appel à SomeMethod peut échouer. Un avertissement CA2000 est déclenché sur cette implémentation.

Dans la méthode OpenPort2, deux objets SerialPort sont déclarés et définis à null :

  • tempPort, utilisé pour tester que les opérations de méthode réussissent.

  • port, utilisé pour la valeur de retour de la méthode.

Le tempPort est construit et ouvert dans un bloc try, et tout autre travail obligatoire est exécuté dans le même bloc try. À la fin du bloc try, le port ouvert est assigné à l'objet port qui sera retourné et l'objet tempPort a la valeur null.

Le bloc finally vérifie la valeur de tempPort. Si sa valeur n'est pas null, une opération dans la méthode a échoué, et tempPort est fermé pour s'assurer que toutes les ressources sont libérées. L'objet de port retourné contiendra l'objet SerialPort ouvert si les opérations de la méthode ont réussi, ou il sera null si une opération a échoué.

Public Function OpenPort1(ByVal PortName As String) As SerialPort

   Dim port As New SerialPort(PortName)
   port.Open()    'CA2000 fires because this might throw
   SomeMethod()   'Other method operations can fail
   Return port

End Function


Public Function OpenPort2(ByVal PortName As String) As SerialPort

   Dim tempPort As SerialPort = Nothing
   Dim port As SerialPort = Nothing

   Try
      tempPort = New SerialPort(PortName)
      tempPort.Open()
      SomeMethod()
      'Add any other methods above this line
      port = tempPort
      tempPort = Nothing

   Finally
      If Not tempPort Is Nothing Then
         tempPort.Close()
      End If


   End Try

   Return port

End Function

Public Function CreateReader1(ByVal x As Integer) As StreamReader
   Dim local As New StreamReader("C:\Temp.txt")
   x += 1
   Return local
End Function


Public Function CreateReader2(ByVal x As Integer) As StreamReader
   Dim local As StreamReader = Nothing
   Dim localTemp As StreamReader = Nothing
   Try
      localTemp = New StreamReader("C:\Temp.txt")
      x += 1
      local = localTemp
      localTemp = Nothing
      Finally
         If (Not (localTemp Is Nothing)) Then
            localTemp.Dispose()
         End If
   End Try
   Return local
End Function

public SerialPort OpenPort1(string portName)
{
   SerialPort port = new SerialPort(portName);
   port.Open();  //CA2000 fires because this might throw
   SomeMethod(); //Other method operations can fail
   return port;
}

public SerialPort OpenPort2(string portName)
{
   SerialPort tempPort = null;
   SerialPort port = null;
   try
   {
      tempPort = new SerialPort(portName);
      tempPort.Open();
      SomeMethod();
      //Add any other methods above this line
      port = tempPort;
      tempPort = null;

   }
   finally
   {
      if (tempPort != null)
      {
         tempPort.Close();
      }
   }
   return port;
}

Par défaut, le compilateur de Visual Basic vérifie le dépassement de capacité de tous les opérateurs arithmétiques de vérifier. Par conséquent, n'importe quelle opération arithmétique de Visual Basic pourrait lever une exception OverflowException. Cela pourrait mener à des violations inattendues de règles telles que CA2000. Par exemple, la fonction CreateReader1 suivante produira une violation CA2000 parce que le compilateur Visual Basic émet une instruction de contrôle de dépassement pour l'addition qui pourrait lever une exception qui provoquerait que le StreamReader ne soit pas supprimé.

Pour résoudre ceci, vous pouvez désactiver l'émission de contrôles de dépassement par le compilateur Visual Basic dans votre projet ou vous pouvez modifier votre code comme la fonction CreateReader2 suivante.

Pour désactiver l'émission de contrôles de dépassement, cliquez avec le bouton droit sur le nom du projet dans l'Explorateur de solutions puis cliquez sur Propriétés. Cliquez sur Compiler, cliquez sur Options avancées de compilation, puis sélectionnez Supprimer les contrôles de dépassement sur les entiers.

Voir aussi

Référence

IDisposable

Implémentation des méthodes Finalize et Dispose pour nettoyer des ressources non managées