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