Должен ли я реализовать GC.SupressFinalize на IDisposable И Finalize?

Контрольный список проверки кода на моем новом клиентском месте имеет следующее:

Класс, реализующий Dispose и Finalize, должен иметь вызов GC.SupressFinalize в реализации Dispose

Почему?

Если он не читается как класс, реализующий интерфейс IDisposable, должен иметь вызов GC.SupressFinalize в реализации Dispose?

Или я что-то глупое упустил?


person Kanini    schedule 05.01.2011    source источник


Ответы (2)


Вы упускаете из виду тот факт, что не каждому одноразовому классу нужен финализатор - фактически, очень немногие, особенно из-за SafeHandle типа .NET 2.0. Если финализатора нет, зачем вам вызывать SuppressFinalize?

person Jon Skeet    schedule 05.01.2011

Это точно. Если метод Dispose (bool) выполнил свою работу, больше нет смысла позволять финализатору сделать это снова. Вызов GC.SuppressFinalize () - это оптимизация, вы не позволяете .NET беспокоиться о вызове финализатора, который ничего не делает.

Я заметил, что вы написали Class с большой буквы. Это намек на то, что вы пишете свой код на VB.NET. Будьте осторожны, IDE делает неправильные вещи в 99,99% всех случаев. Как только вы нажимаете Enter после ввода «Implements IDisposable», он вставляет неправильный код:

    Private disposedValue As Boolean = False        ' To detect redundant calls

    ' IDisposable
    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing Then
                ' TODO: free other state (managed objects).
            End If

            ' TODO: free your own state (unmanaged objects).
            ' TODO: set large fields to null.
        End If
        Me.disposedValue = True
    End Sub

#Region " IDisposable Support "
    ' This code added by Visual Basic to correctly implement the disposable pattern.
    Public Sub Dispose() Implements IDisposable.Dispose
        ' Do not change this code.  Put cleanup code in Dispose(ByVal disposing As Boolean) above.
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
#End Region

Фу. Это шаблонная реализация финализатора, хорошо документированная, кстати, в библиотеке MSDN. Это не правильно. Крайне редко действительно нужен финализатор, классы .NET уже позаботятся об этом сами. Если вы действительно используете дескриптор операционной системы, вам следует использовать один из производных классов SafeHandle. Или напишите свою обертку.

Отредактируйте его обратно на это:

Public Sub Dispose() Implements IDisposable.Dispose
    someField.Dispose()
    '' maybe some more
    ''...
End Sub
person Hans Passant    schedule 05.01.2011