Appeler GC.SuppressFinalize correctement
Mise à jour : novembre 2007
TypeName |
CallGCSuppressFinalizeCorrectly |
CheckId |
CA1816 |
Catégorie |
Microsoft. Utilisation |
Modification avec rupture |
Modification sans rupture |
Cause
Une méthode qui est une implémentation de Dispose n'appelle pas GC.SuppressFinalize.
- ou -
Une méthode qui n'est pas une implémentation de Dispose appelle GC.SuppressFinalize.
- ou -
Une méthode appelle GC.SuppressFinalize et passe une valeur différente de this (Me en Visual Basic).
Description de la règle
La méthode Dispose permet aux utilisateurs de libérer des ressources n'importe quand avant que l'objet devienne disponible pour l'opération garbage collection. Si la méthode Dispose est appelée, elle libère les ressources de l'objet. Cela rend la finalisation inutile. Dispose doit appeler GC.SuppressFinalize afin que le garbage collector n'appelle pas le finaliseur de l'objet.
Pour éviter que les types dérivés avec finaliseurs ne doivent réimplémenter [System.IDisposable] et l'appeler, des types unsealed sans finaliseur doivent toujours appeler GC.SuppressFinalize.
Comment corriger les violations
Pour corriger une violation de cette règle :
Si la méthode est une implémentation de Dispose, ajoutez un appel à GC.SuppressFinalize.
Si la méthode n'est pas une implémentation de Dispose, supprimez l'appel à GC.SuppressFinalize ou déplacez-le vers l'implémentation Dispose du type.
Modifiez tous les appels à GC.SuppressFinalize pour passer this (Me en Visual Basic).
Quand supprimer les avertissements
Supprimez uniquement un avertissement de cette règle si vous utilisez délibérément GC.SuppressFinalize pour contrôler la durée de vie des autres objets. Ne supprimez pas un avertissement de cette règle si une implémentation de Dispose n'appelle pas GC.SuppressFinalize. Dans cette situation, ne pas parvenir à supprimer une finalisation fait baisser les performances et n'apporte aucun avantage.
Exemple
L'exemple suivant montre une méthode qui appelle GC.SuppressFinalize de manière incorrecte en lui passant true (True en Visual Basic).
Imports System
Imports System.Data.SqlClient
Namespace Samples
Public Class DatabaseConnector
Implements IDisposable
Private _Connection As New SqlConnection
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(True) ' Violates rules
End Sub
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If _Connection IsNot Nothing Then
_Connection.Dispose()
_Connection = Nothing
End If
End If
End Sub
End Class
End Namespace
using System;
using System.Data.SqlClient;
namespace Samples
{
public class DatabaseConnector : IDisposable
{
private SqlConnection _Connection = new SqlConnection();
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(true); // Violates rule
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (_Connection != null)
{
_Connection.Dispose();
_Connection = null;
}
}
}
}
}
L'exemple suivant montre une méthode qui appelle GC.SuppressFinalize de manière correcte.
Imports System
Imports System.Data.SqlClient
Namespace Samples
Public Class DatabaseConnector
Implements IDisposable
Private _Connection As New SqlConnection
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If _Connection IsNot Nothing Then
_Connection.Dispose()
_Connection = Nothing
End If
End If
End Sub
End Class
End Namespace
using System;
using System.Data.SqlClient;
namespace Samples
{
public class DatabaseConnector : IDisposable
{
private SqlConnection _Connection = new SqlConnection();
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (_Connection != null)
{
_Connection.Dispose();
_Connection = null;
}
}
}
}
}
Règles connexes
Les types pouvant être supprimés doivent déclarer un finaliseur
Voir aussi
Référence
Implémentation des méthodes Finalize et Dispose pour nettoyer des ressources non managées