Partager via


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