Solución:
SuppressFinalize
solo debe ser llamado por una clase que tenga un finalizador. Está informando al recolector de basura (GC) que this
El objeto se limpió completamente.
El recomendado IDisposable
patrón cuando tienes un finalizador es:
public class MyClass : IDisposable
{
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// called via myClass.Dispose().
// OK to use any private object references
}
// Release unmanaged resources.
// Set large fields to null.
disposed = true;
}
}
public void Dispose() // Implement IDisposable
{
Dispose(true);
GC.SuppressFinalize(this);
}
~MyClass() // the finalizer
{
Dispose(false);
}
}
Normalmente, CLR controla los objetos con un finalizador cuando se crean (lo que hace que su creación sea más cara). SuppressFinalize
le dice al GC que el objeto se limpió correctamente y no necesita ir a la cola del finalizador. Parece un destructor de C ++, pero no actúa como tal.
los SuppressFinalize
La optimización no es trivial, ya que sus objetos pueden vivir mucho tiempo esperando en la cola del finalizador. No tengas la tentación de llamar SuppressFinalize
en otros objetos, fíjate. Ese es un defecto grave que está a punto de ocurrir.
Las pautas de diseño nos informan que no es necesario un finalizador si su objeto implementa IDisposable
, pero si tiene un finalizador, debe implementar IDisposable
para permitir una limpieza determinista de su clase.
La mayoría de las veces debería poder salirse con la suya IDisposable
para limpiar los recursos. Solo debe necesitar un finalizador cuando su objeto se aferre a recursos no administrados y debe garantizar que esos recursos se limpien.
Nota: A veces, los codificadores agregarán un finalizador para depurar sus propias compilaciones. IDisposable
clases para probar que el código ha eliminado su IDisposable
objeto correctamente.
public void Dispose() // Implement IDisposable
{
Dispose(true);
#if DEBUG
GC.SuppressFinalize(this);
#endif
}
#if DEBUG
~MyClass() // the finalizer
{
Dispose(false);
}
#endif
SupressFinalize
le dice al sistema que cualquier trabajo que se habría realizado en el finalizador ya se ha realizado, por lo que no es necesario llamar al finalizador. De los documentos de .NET:
Los objetos que implementan la interfaz IDisposable pueden llamar a este método desde el método IDisposable.Dispose para evitar que el recolector de basura llame a Object.Finalize en un objeto que no lo requiere.
En general, la mayoría Dispose()
el método debería poder llamar GC.SupressFinalize()
, porque debería limpiar todo lo que se limpiaría en el finalizador.
SupressFinalize
es solo algo que proporciona una optimización que permite que el sistema no se moleste en colocar el objeto en la cola del subproceso del finalizador. Un escrito correctamente Dispose()
/ finalizer debería funcionar correctamente con o sin una llamada a GC.SupressFinalize()
.