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 :
Dans une classe non scellée, une méthode qui est une implémentation de IDisposable.Dispose et n’appelle pas GC.SuppressFinalize.
Une méthode qui n’est pas une implémentation de IDisposable.Dispose et appelle GC.SuppressFinalize.
Une méthode qui appelle GC.SuppressFinalize et transmet quelque chose d’autre que this (C#) ou Me (Visual Basic).
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 :
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.
Remplacez tous les appels à GC.SuppressFinalize pour passer this (C#) ou Me (Visual Basic).
Si le type n’est pas destiné à être remplacé, marquez-le comme
sealed
.
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;
}
}
}
}
Règles associées
- CA2215 : Les méthodes Dispose doivent appeler la méthode Dispose de la classe de base
- CA2216 : Les types pouvant être supprimés doivent déclarer un finaliseur