2008-09-22 21 views
5

En Visual Studio, al escribir la línea "Implements IDisposable", el IDE agrega automáticamente:VB.NET - ¿Se debe agregar un método Finalize al implementar IDisposable?

  • una variable disposedValue miembro de
  • un Sub Dispose() Implements IDisposable.Dispose
  • un Sub Dispose(ByVal disposing As Boolean)

El Dispose() debería haber solo, y el código de limpieza debe ponerse en Dispose(disposing).

Sin embargo, el Dispose Finalize Pattern dice que también debe anular Sub Finalize() para llamar al Dispose(False). ¿Por qué el IDE también agrega esto? ¿Debo agregarlo yo mismo, o de alguna manera se lo llama implícitamente?

EDIT: ¿Alguna idea de por qué el IDE agrega automáticamente el 80% de las cosas necesarias pero deja fuera el método Finalize? ¿No es el objetivo de este tipo de función ayudarlo no olvidar estas cosas?

EDIT2: Gracias a todos por sus excelentes respuestas, ¡esto ahora tiene mucho sentido!

Respuesta

11

Si en realidad tiene recursos no administrados que no serán limpiados automáticamente por el recolector de basura y los limpia en su Dispose(), entonces sí, debe hacer lo mismo en Finalize().

Si está implementando IDisposable por algún otro motivo, no es necesario implementar Finalize().

La pregunta básica es esta: si no se llamó a Dispose() y se recolectó su objeto basura, ¿la memoria podría perder? En caso afirmativo, implemente Finalize. Si no, no es necesario. Además, evite implementar Finalize "solo porque sea más seguro". Los objetos con finalizadores personalizados pueden necesitar dos pases de GC para liberarlos, una para ponerlos en la cola de finalizadores pendientes y una segunda pasada para liberar realmente su memoria.

+1

Implementar Eliminar no significa que también deba implementar un finalizador. Puede liberar recursos no administrados en un método de eliminación sin necesidad de un finalizador. Si debe implementar un finalizador, su lógica de limpieza real debe estar en una función separada que elimine y finalice la llamada. –

+1

Eso es incorrecto.Si confía únicamente en Dispose() para liberar recursos no administrados, la memoria se fugará en los casos en que no se invoque Dispose. Para eso está el finalizador. – Laurent

+1

No estoy seguro de por qué no contesté el comentario anterior de Scott, no debo haberlo notado, pero Laurent tiene razón, si su Dispose está limpiando recursos no administrados, se requiere una Finalize para mayor seguridad. No lo dejes porque eres flojo. –

3

No, no necesita tener Finalize a menos que tenga recursos no administrados para limpiar.

En la mayoría de los casos, la razón por la cual una clase es desechable es porque mantiene referencias a otros objetos administrables IDisposable. En este caso, ningún método de Finalización es necesario o deseable.

+0

Puede liberar recursos no administrados en un método de eliminación sin necesitar un finalizador. –

+0

Puede hacerlo, pero si no se invoca a Dispose, es probable que también se pierda la memoria sin un método Finalize. –

1

Como han dicho otros, no es necesario implementar un finalizador a menos que esté manteniendo directamente recursos no administrados. Además, suponiendo que esté trabajando en .NET 2.0 o posterior, es poco probable que necesite implementar un finalizador porque, por lo general, SafeHandle puede usarse para ajustar sus recursos no administrados.

Escribí un fairly long blog post cubriendo los antecedentes y la implementación de IDisposable y finalizadores hace un tiempo, que puede valer la pena leer si no está totalmente claro al respecto.

+0

Puede liberar recursos no administrados en un método de eliminación sin necesidad de un finalizador. –

+0

Bueno, sí, ese es el objetivo del patrón IDisposable. Sin embargo, si las personas olvidan llamar a Dispose, el finalizador es una salvaguarda que los limpia eventualmente, que no puede olvidarse porque es invocado por el tiempo de ejecución. –

2
Implements IDisposable 

Public Overloads Sub Dispose() Implements IDisposable.Dispose 

    Dispose(True) 
    GC.SuppressFinalize(Me) 

End Sub 

Protected Overloads Sub Dispose(ByVal disposing As Boolean) 

    If disposing Then 
     ' Free other state (managed objects). 
    End If 
    ' Free your own state (unmanaged objects). 
    ' Set large fields to null. 
End Sub 

Protected Overrides Sub Finalize() 

    Dispose(False) 
    MyBase.Finalize() 

End Sub 
+3

Una sola losa de código no es muy útil. Intenta ser más constructivo, con una pequeña descripción y razonamiento detrás del código proporcionado. –

Cuestiones relacionadas