Реализовать Утилизировать или Завершить? - PullRequest
2 голосов
/ 15 февраля 2010
Class ComponentsContainer   ' a component contains other components'
    Inherits System.ComponentModel.Component

    Private foo as New Component
    Private bar as New Component

Protected Override Sub Finalize()
    foo.Dispose()  ' HERE ? '
    bar.Dispose()
    MyBase.Finalize()
End Sub

Protected Overrides Sub Dispose(disposing As Boolean)
    If disposing Then
        foo.Dispose() ' OR HERE ? '
        bar.Dispose()
    End If
    MyBase.Dispose(disposing)
End Sub 
End Class

Ответы [ 4 ]

3 голосов
/ 15 февраля 2010

Финализатор должен вызывать этот класс 'Dispose, передавая false для параметра распоряжения, а не непосредственно уничтожая объекты, которыми владеет этот класс. См. MSDN .

Редактировать: Таким образом, чтобы ответить на вопрос, удаление принадлежащих объектов должно быть выполнено в Dispose, а не Finalize.

Редактировать 2: Обратите внимание, это означает, что если объект завершается без удаления, тогда Dispose будет вызываться (с помощью Finalize) только с параметром "false", а дочерние объекты не будут распоряжаться этим классом. Это правильно, потому что они являются управляемыми объектами и будут завершены, когда инфраструктура будет чувствовать себя, как если бы она не была явно удалена.

3 голосов
/ 15 февраля 2010

Вы не должны (не обязаны) распоряжаться управляемыми ресурсами из финализатора:

Protected Override Sub Finalize()
    ' foo.Dispose()  ' 
    ' bar.Dispose()  '
    MyBase.Finalize()
End Sub

Из этого следует, что если у вашего класса нет неуправляемых ресурсов, вам вообще не нужен финализатор.

Примечание. В вашем классе отсутствует перегрузка Public Sub Dispose().

Edit:

Поскольку foo и bar являются управляемыми ресурсами (расширяющий компонент), вам нужен только метод Protected Overrides Sub Dispose(disposing As Boolean). Версия в вопросе верна. И просто бросьте Finalize().

1 голос
/ 15 февраля 2010

От чего вы наследуете? Я подозреваю, что это может быть System.ComponentModel.Container , прямо или косвенно.

В этом случае вам не нужно ничего делать. System.ComponentModel.Container автоматически удаляет все содержащиеся в нем компоненты в методе Dispose Оставьте в покое - это должен быть самый простой способ реализовать шаблон dispose / finalize.

1 голос
/ 15 февраля 2010

Dispose - это когда вы явно хотите освободить некоторые ресурсы до того, как сборщик мусора освободит объект.

Finalize автоматически вызывается, когда или если сборщик мусора приступает к освобождению объекта.

Если у вас много объектов, удерживающих ресурс, то, поскольку вы не должны контролировать сборку мусора, вам следует использовать Dispose.

Из базовой документации:

Обратите внимание, что даже когда вы предоставляете явный контроль посредством Dispose, Вы должны обеспечить неявную очистку используя метод Finalize. завершать предоставляет резервную копию для предотвращения ресурсов от постоянной утечки, если Программист не может вызвать Dispose.

Реализация завершить и утилизировать для очистки неуправляемых ресурсов

...