2009-04-20 13 views
7

He estado programando en .NET durante cuatro años (principalmente C#) y uso IDiposable extensivamente, pero aún no he encontrado la necesidad de un finalizador. ¿Para qué sirven los finalizadores?¿Para qué sirven los finalizadores?

+5

Por cierto, soy inglés, y he descubierto que es una * realmente * * realmente * buena idea tener el hábito de deletrear "finalizar" e "inicializar" con una z, no una s. De lo contrario, nunca podrá encontrar las cosas sangrientas cuando las busque en la documentación. –

+1

@onebyone - ídem. Del mismo modo, Color ... solía causarme irritación, pero ahora solo los considero el término técnico para la industria, y hago el trabajo ;-p –

+0

He estado tratando de entrenarme a mí mismo, lo uso en documentación y en público frente al código, pero simplemente no puedo obligarme a hacerlo en "la vida real". –

Respuesta

10

un finalizador es un último intento para asegurar que algo se limpia correctamente, y por lo general se reserva para los objetos que envuelven no administrados recursos, tales como manijas, etc no administrados que no quede basura recogida.

De hecho, es raro escribir un finalizador. Afortunadamente (y a diferencia de IDisposable), los finalizadores no necesitan ser propagados; entonces si tiene un ClassA con un finalizador, y un ClassB que envuelve ClassA, entonces ClassB no necesita un finalizador, pero muy probablemente ClassA y implementarían IDisposable.

Para el código administrado, IDisposable suele ser suficiente. Incluso si no se limpia correctamente, con el tiempo los objetos gestionados se recopilarán (suponiendo que se liberen).

1

Los finalizadores son para limpiar los recursos si no fueron desechados.

IE, no hace falta nada que llame Dispose(), pero los finalizadores son llamados automáticamente por el recolector de elementos no utilizados.

No se debe confiar en esta funcionalidad, ya que no hay garantía de cuándo (o si) la recolección de basura llegará a su objeto.

2

Los finalizadores son un mecanismo para liberar recursos no controlados por el recolector de basura, como un controlador no administrado. Si bien Dispose podría hacerlo, no se garantiza que el consumidor lo llame.

4

Los finalizadores son solo para liberar recursos no administrados como los identificadores de mapa de bits de GDI, por ejemplo. Si no asigna ningún recurso no administrado, entonces no necesita finalizadores. En general, es una mala idea tocar cualquier objeto administrado en un finalizador porque el orden de finalización no está garantizado.

Otra técnica útil que utiliza un finalizador es afirmar que se ha llamado a Dispose cuando se requiere que la aplicación lo haga. Esto puede ayudar a detectar errores de codificación en una versión de depuración:

void Dispose() 
{ 
    GC.SuppressFinalize(this); 
} 
#if DEBUG 
~MyClass() 
{ 
    Debug.Fail("Dispose was not called."); 
} 
#endif 
1

Wikipedia says:

... un finalizador es una pieza de código que asegura que ciertas acciones necesarias se toman cuando una adquirida recursos ... ya no está siendo utilizada [debido a que el objeto propietario ha sido recogido de basura ]

Y si no está usando un finalizador cuando está escribiendo IDisposables, es muy probable que tenga pérdidas de memoria, porque no hay garantía de que un propietario vaya a llamar a Dispose().

MS sí recomiendo que escriba algo similar a esto en sus ejecutores:

public void Dispose() 
    { 
     this.Dispose(true); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
     if (!this.isDisposed) 
     { 
      if (disposing) 
      { 
       GC.SuppressFinalize(this); 
      } 
     } 
     //Dispose of resources here 
     this.isDisposed = true; 
    } 

    ~DisposableSafe() 
    { 
     this.Dispose(false); 
    } 

    private bool isDisposed = false; 

Personalmente, no puedo soportar el copiar y pegar lo que tienden a envolver que en una clase abstracta para su reutilización.

+0

A menos que su clase trate directamente con recursos * no administrados, entonces probablemente no necesite un finalizador. Los recursos administrados eventualmente deberían ser tratados por el GC, independientemente de si el usuario llama a Dispose o no. – LukeH

+0

Esto es lo que me hizo escribir "posiblemente" en lugar de "probablemente" y eso me preocupaba. Pero no es del todo cierto de todos modos. Si su clase implementa algún otro IDisposable, entonces tiene la responsabilidad de llamar a Dispose() también. Y a medida que avanza, desde MSDN "El uso principal de esta interfaz es liberar recursos no administrados". – annakata

Cuestiones relacionadas