Compartir a través de


Llamar a GC.SuppressFinalize correctamente

Actualización: noviembre 2007

Nombre de tipo

CallGCSuppressFinalizeCorrectly

Identificador de comprobación

CA1816

Categoría

Microsoft. Usage

Cambio problemático

No

Motivo

Un método que es una implementación de Dispose no llama a GC.SuppressFinalize.

O bien

Un método que no es una implementación de Dispose llama a GC.SuppressFinalize.

O bien

Un método llama a GC.SuppressFinalize y pasa algo distinto de this (Me en Visual Basic).

Descripción de la regla

El método 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 Dispose, este método libera los recursos del objeto. Por ello, la finalización resulta innecesaria. 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 a GC.SuppressFinalize de modo que pasen this (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 de manera incorrecta pasándole true (True en Visual Basic).

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

Los tipos disponibles deben declarar el finalizador

Vea también

Referencia

Implementar Finalize y Dispose para limpiar recursos no administrados