Partager via


CA1816 : Appeler GC.SuppressFinalize correctement

TypeName

CallGCSuppressFinalizeCorrectly

CheckId

CA1816

Catégorie

Microsoft. Utilisation

Modification avec rupture

Modification sans rupture

Cause

Description de la règle

La méthode IDisposable.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 IDisposable.Dispose est appelée, elle libère les ressources de l'objet. Cela rend la finalisation inutile. IDisposable.Dispose doit appeler GC.SuppressFinalize ainsi 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 enGC.SuppressFinalize pour passer ceci (Moi 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.

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

CA2215 : Les méthodes Dispose doivent appeler la fonction Dispose de la classe de base

CA2216 : 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