Compartir a través de


CA1816: Llamar a GC.SuppressFinalize correctamente

Nombre de tipo

CallGCSuppressFinalizeCorrectly

Identificador de comprobación

CA1816

Categoría

Microsoft.Uso

Cambio problemático

No

Motivo

Descripción de la regla

El método IDisposable.Dispose permite a los usuarios liberar los recursos en cualquier momento antes de que el objeto se encuentre disponible para la recolección de elementos no utilizados.Si se llama al método IDisposable.Dispose, este método libera los recursos del objeto.Esto hace la finalización 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 implementar de nuevo [System.IDisposable] y tengan que llamarlo, los tipos no sellados deben llamar a GC.SuppressFinalize.

Cómo corregir infracciones

Para corregir una infracción de esta regla:

Si el método es una implementación de Dispose, agregue una llamada a GC.SuppressFinalize.

Si el método no es ninguna implementación de Dispose, quite la llamada a GC.SuppressFinalize o muévala a la implementación Dispose del tipo.

Cambie todas las llamadas por GC.SuppressFinalize para pasar esto (Me en Visual Basic).

Cuándo suprimir advertencias

Únicamente debe suprimir una advertencia de esta regla si está utilizando de forma deliberada 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, si se suprime la finalización erróneamente, se reduce el rendimiento y no se obtienen ventajas.

Ejemplo

En el ejemplo siguiente se muestra un método que llama a GC.SuppressFinalize incorrectamente.

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

En el ejemplo siguiente se muestra un método que llama a GC.SuppressFinalize correctamente.

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

Reglas relacionadas

CA2215: Los métodos Dispose deben llamar a Dispose de clase base

CA2216: Los tipos descartables deben declarar el finalizador

Vea también

Referencia

Implementing Finalize and Dispose