CA1816: Llamar a GC.SuppressFinalize correctamente

Propiedad Value
Identificador de la regla CA1816
Título Llamar a GC.SuppressFinalize correctamente
Categoría Uso
La corrección es problemática o no problemática Poco problemático
Habilitado de forma predeterminada en .NET 8 Como sugerencia

Causa

Las infracciones de esta regla pueden deberse a los factores siguientes:

Descripción de la regla

El método IDisposable.Dispose permite a los usuarios liberar recursos en cualquier momento antes de que el objeto esté disponible para la recolección de elementos no utilizados. Si se llama al método IDisposable.Dispose, este libera los recursos del objeto. Esto hace que la finalización sea innecesaria. IDisposable.Dispose debe llamar a GC.SuppressFinalize para que el recolector de elementos no utilizados no llame al finalizador del objeto.

Para evitar que los tipos derivados con finalizadores tengan que volver a implementar IDisposable y llamarlo, los tipos no sellados sin finalizadores deben seguir llamando a GC.SuppressFinalize.

Cómo corregir infracciones

Para corregir una infracción de esta regla haga lo siguiente:

Cuándo suprimir las advertencias

Solo debes suprimir una advertencia de esta regla si usa deliberadamente GC.SuppressFinalize para controlar la duración de otros objetos. No suprima una advertencia de esta regla si una implementación de Dispose no llama a GC.SuppressFinalize. En esta situación, el hecho de no suprimir la finalización degrada el rendimiento y no ofrece ninguna ventaja.

Supresión de una advertencia

Si solo quiere suprimir una única infracción, agregue directivas de preprocesador al archivo de origen para deshabilitar y volver a habilitar la regla.

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

Para deshabilitar la regla de un archivo, una carpeta o un proyecto, establezca su gravedad en none del archivo de configuración.

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

Para obtener más información, consulte Procedimiento para suprimir advertencias de análisis de código.

Ejemplo que infringe la regla CA1816

Este código muestra un método que llama a GC.SuppressFinalize, pero no pasa this (C#) ni Me (Visual Basic). Como resultado, este código infringe la regla 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;
            }
        }
    }
}

Ejemplo que cumple la regla CA1816

Este código muestra un método que llama correctamente a GC.SuppressFinalize pasando this (C#) o 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;
            }
        }
    }
}

Consulte también