CA1816: Llamar a GC.SuppressFinalize correctamente
TypeName |
CallGCSuppressFinalizeCorrectly |
Identificador de comprobación |
CA1816 |
Categoría |
Microsoft.Uso |
Cambio problemático |
No |
Motivo
Un método que es una implementación de IDisposable.Dispose no llama a GC.SuppressFinalize.
Un método que no es una implementación de IDisposable.Dispose llama a GC.SuppressFinalize.
Un método llama a GC.SuppressFinalize y pasa algo distinto de esto (Me en Visual Basic).
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