Compartir vía


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 10 Como sugerencia

Causa

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

Descripción de la regla

El IDisposable.Dispose método 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 MyStreamClass
    Implements IDisposable

    Private _stream As New MemoryStream

    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
        ' Violates rule.
        GC.SuppressFinalize(True)
    End Sub

    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If _stream IsNot Nothing Then
                _stream.Dispose()
                _stream = Nothing
            End If
        End If
    End Sub

End Class
public class MyStreamClass : IDisposable
{
    private MemoryStream? _stream = new();

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(true);  // Violates rule
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            _stream?.Dispose();
            _stream = 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 MyStreamClass
    Implements IDisposable

    Private _stream As New MemoryStream

    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 _stream IsNot Nothing Then
                _stream.Dispose()
                _stream = Nothing
            End If
        End If
    End Sub

End Class
public class MyStreamClass : IDisposable
{
    private MemoryStream? _stream = new();

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            _stream?.Dispose();
            _stream = null;
        }
    }
}

Consulte también