En .NET, ¿bajo qué circunstancias debo usar GC.SuppressFinalize()
?¿Cuándo debería usar GC.SuppressFinalize()?
¿Qué ventaja (s) me otorga usar este método?
En .NET, ¿bajo qué circunstancias debo usar GC.SuppressFinalize()
?¿Cuándo debería usar GC.SuppressFinalize()?
¿Qué ventaja (s) me otorga usar este método?
Solo una clase que tiene un finalizador debe invocar SuprimirFinalizar. Está informando al recolector de basura (GC) que el objeto this
se limpió por completo.
El patrón IDisposable recomendada cuando se tiene 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, el CLR tiene tablas sobre objetos con un finalizador cuando se crean (haciéndolos más costosos de crear). 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 uno.
La optimización SuprimirFinalizar no es trivial, ya que sus objetos pueden vivir mucho tiempo esperando en la cola del finalizador. No tengas la tentación de invocar SuppressFinalize en otros objetos. Ese es un defecto serio que está por suceder.
Las pautas de diseño nos informan que un finalizador no es necesario si su objeto implementa IDisposable, pero si tiene un finalizador debe implementar IDisposable para permitir la limpieza determinista de su clase.
La mayoría de las veces usted debe poder salir con IDisposable para limpiar los recursos. Solo debe necesitar un finalizador cuando su objeto se atenga a recursos no administrados y debe garantizar que esos recursos se limpien.
Nota: A veces los codificadores agregarán un finalizador para depurar compilaciones de sus propias clases IDisposable para probar que el código ha eliminado correctamente su objeto IDisposable.
public void Dispose() // Implement IDisposable
{
Dispose(true);
#if DEBUG
GC.SuppressFinalize(this);
#endif
}
#if DEBUG
~MyClass() // the finalizer
{
Dispose(false);
}
#endif
Estoy de acuerdo con su código, pero pondría una afirmación en la versión de depuración ... y si el recurso que se elimina es costoso, dejaré el finalizador en la publicación de lanzamiento. –
En el primer fragmento de código, solo estoy publicando el aspecto del patrón IDisposable + finalizer recomendado. El código de depuración es bueno, pero puede distraer. .. Solo puedo recomendar evitar los finalizadores excepto para las clases que tienen recursos no administrados. Escribir un código de finalizador seguro no es trivial. –
¿Puedo usar el patrón de eliminación en una clase base y extenderlo entre otros uno? –
Ese método debe invocarse en el método Dispose de los objetos que implementan el IDisposable, de esta forma el GC no llamaría al finalizador en otro momento si alguien llama al método Dispose.
Ver: http://msdn.microsoft.com/en-us/library/system.gc.suppressfinalize.aspx
Creo que "Must" está mal, ni siquiera "debería" - Es solo que en algunos escenarios, puede eliminar la sobrecarga de poner en cola/finalizar el objeto. – Basic
usted está diciendo al sistema que cualquier trabajo que se habría hecho en el finalizador ya se ha hecho, por lo que el finalizador no necesita ser llamado. A partir de la documentación de .NET:
Objetos que implementan la interfaz IDisposable puede llamar a este método de el método IDisposable.Dispose a prevenir el recolector de basura de llamando Object.Finalize en un objeto que no requiere eso.
En general, la mayoría de los métodos de Dispose() deberían poder llamar a GC.SupressFinalize(), ya que deberían limpiar todo lo que sería correcto en el finalizador.
SupressFinalize es simplemente algo que proporciona una optimización que permite que el sistema no se moleste en buscar el objeto en la secuencia del finalizador. Un Dispose()/finalizer correctamente escrito debería funcionar correctamente con o sin una llamada a GC.SupressFinalize().
he visto algunas preguntas acerca de los finalizadores y IDisposable, stackoverflow también debe tener algo de GC.SupressFinalize y referencias débiles –
no creo referencias débiles hacer nada con respecto a los finalizadores - tal vez debería poner un mayor pregunta directa sobre ellos. –
Yerp Quise publicar una pregunta por separado sobre los refs débiles, todo esto puede vincularse cuando construyes grupos de objetos. También debería hacer una pregunta sobre la reactivación de objetos ala ReRegisterForFinalize –