En Visual Basic, la implementación de la interfaz IDisposable (patrón Dispose) permite liberar correctamente los recursos (por ejemplo, archivos, conexiones de bases de datos, objetos gráficos) que no son gestionados por el recolector de basura.
Una implementación típica es la siguiente:
Public Class FileManager Implements IDisposable Private fileStream As FileStream Private disposed As Boolean = False Public Sub New(path As String) fileStream = New FileStream(path, FileMode.Open) End Sub Public Sub Dispose() Implements IDisposable.Dispose Dispose(True) GC.SuppressFinalize(Me) End Sub Protected Overridable Sub Dispose(disposing As Boolean) If Not disposed Then If disposing AndAlso fileStream IsNot Nothing Then fileStream.Dispose() End If disposed = True End If End Sub Protected Overrides Sub Finalize() Dispose(False) MyBase.Finalize() End Sub End Class
Importante: Utiliza la construcción Using ... End Using — garantiza que Dispose se llame automáticamente:
Using manager As New FileManager("data.txt") ' operaciones con el archivo End Using
Matices:
Pregunta: "¿Por qué es necesario llamar a GC.SuppressFinalize(Me) dentro del método Dispose?"
Respuesta correcta: Informa al recolector de basura que el finalizador (Finalizer) no necesita ser llamado, ya que los recursos ya han sido limpiados manualmente a través de Dispose. Sin esto, el finalizador se ejecutará una vez de más, lo que reducirá el rendimiento y puede provocar una limpieza duplicada.
Historia
En un software bancario, se implementó incorrectamente IDisposable — olvidaron llamar a Dispose en la base de datos, lo que llevó a fugas de conexiones. En promedio, la aplicación "se congelaba" después de 2-3 días de funcionamiento continuo.
Historia
En un servicio médico, se implementó incorrectamente Dispose (faltaba el indicador "disposed"). Se llamó al método Dispose muchas veces consecutivas, lo que llevó a intentos de liberar el mismo recurso varias veces y a la aparición de excepciones.
Historia
En un editor gráfico, olvidaron llamar a GC.SuppressFinalize(Me). El finalizador se ejecutaba incluso después de Dispose, lo que llevaba a una liberación duplicada de recursos y a inestabilidad (violación de acceso).