CA1816 : Appeler GC.SuppressFinalize correctement

Propriété Value
Identificateur de la règle CA1816
Titre Appeler GC.SuppressFinalize correctement
Catégorie Utilisation
Le correctif est cassant ou non cassant Sans rupture
Activé par défaut dans .NET 8 À titre de suggestion

Cause

Les violations de cette règle peuvent être provoquées par :

Description de la règle

La méthode IDisposable.Dispose permet aux utilisateurs de libérer des ressources à tout moment avant que l’objet soit disponible pour le 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 afin que le garbage collector n’appelle pas le finaliseur de l’objet.

Pour empêcher les types dérivés avec des finaliseurs d’avoir à réapprouver IDisposable et de l’appeler, les types non scellés sans finaliseurs doivent toujours appeler GC.SuppressFinalize.

Comment corriger les violations

Pour corriger toute violation de cette règle :

Quand supprimer les avertissements

Supprimez uniquement un avertissement de cette règle si vous utilisez GC.SuppressFinalize délibérément pour contrôler la durée de vie d’autres objets. Ne supprimez pas d’avertissement de cette règle si une implémentation de Dispose n’appelle pas GC.SuppressFinalize. Dans ce cas, l’échec de la suppression de la finalisation dégrade les performances et n’offre aucun avantage.

Supprimer un avertissement

Si vous voulez supprimer une seule violation, ajoutez des directives de préprocesseur à votre fichier source pour désactiver et réactiver la règle.

#pragma warning disable CA1816
// The code that's violating the rule is on this line.
#pragma warning restore CA1816

Pour désactiver la règle sur un fichier, un dossier ou un projet, définissez sa gravité sur none dans le fichier de configuration.

[*.{cs,vb}]
dotnet_diagnostic.CA1816.severity = none

Pour plus d’informations, consultez Comment supprimer les avertissements de l’analyse de code.

Exemple qui enfreint la règle CA1816

Ce code montre une méthode qui appelle GC.SuppressFinalize, mais ne passe pas this (C#) ou Me (Visual Basic). Par conséquent, ce code enfreint la règle CA1816.

Public Class DatabaseConnector
    Implements IDisposable

    Private _Connection As New SqlConnection

    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
        ' Violates rules
        GC.SuppressFinalize(True)
    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
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;
            }
        }
    }
}

Exemple qui satisfait à CA1816

Cet exemple montre une méthode qui appelle GC.SuppressFinalize correctement en passant this (C#) ou Me (Visual Basic).

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
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;
            }
        }
    }
}

Voir aussi