В Visual Basic реализация интерфейса IDisposable (паттерн Dispose) позволяет корректно освобождать ресурсы (например, файлы, соединения БД, графические объекты), которые не управляются сборщиком мусора.
Типичная реализация следующая:
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
Важно: Используйте конструкцию Using ... End Using — она гарантирует вызов Dispose автоматически:
Using manager As New FileManager("data.txt") ' операции с файлом End Using
Тонкости:
Вопрос: "Зачем нужен вызов GC.SuppressFinalize(Me) внутри метода Dispose?"
Правильный ответ: Он сообщает сборщику мусора, что финализатор (Finalizer) можно не вызывать, так как ресурсы уже были вручную очищены через Dispose. Без этого финализатор отработает лишний раз, что снизит производительность и может привести к дублирующей очистке.
История
В банковском ПО некорректно реализовали IDisposable — забыли вызывать Dispose у базы данных, что привело к утечке соединений. В среднем приложение "подвисало" через 2–3 дня непрерывной работы.
История
В медицинском сервисе неверно реализовали Dispose (отсутствовал флаг "disposed"). Метод Dispose вызывался много раз подряд, что приводило к попыткам повторного освобождения одного и того же ресурса и возникновению исключений.
История
В графическом редакторе забыли вызвать GC.SuppressFinalize(Me). Финализатор выполнялся даже после Dispose, приводя к двойному освобождению ресурсов и нестабильности (access violation).