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
Implémentation des méthodes Finalize et Dispose pour nettoyer des ressources non managées