Вопросы 1 и 2 : CLR в основном проверяет, переопределен ли финализатор. Если это не так, он рассматривает это как отсутствие финализатора.
Преимущество наличия финализатора в System.Object заключается в том, что компиляторы знают, что они могут всегда вызывать base.Finalize()
in. Это позволяет избежать проблем с версиями. Рассмотрим мир без System.Object.Finalize()
:
- System.Object (без финализации)
- Acme.BaseClass (без финализации)
- MyCompany.DerivedClass (Завершить)
Без метода Finalize
в объекте финализатор в MyCompany.DerivedClass не может ничего вызывать. Что приводит к проблеме, когда версия 2 Acme.BaseClass выходит с финализатором. Если вы не перекомпилируете MyCompany.DerivedClass, экземпляр DerivedClass будет завершен без вызова BaseClass.Finalize, что явно является плохим.
Теперь рассмотрим ту же ситуацию с System.Object.Finalize - компилятор вставляет вызов base.Finalize автоматически в DerivedClass.Finalize, который в версии 1 просто вызывает реализацию no-op в System. Объект. Когда выйдет версия 2 Acme.BaseClass, вызов base.Finalize
вызовет (без перекомпиляции DerivedClass) вызов BaseClass.Finalize.
Вопрос 3 : Нет, вам не нужно иметь финализатор только потому, что вы реализуете IDisposable. Финализаторы должны использоваться только для неуправляемых ресурсов, которые больше не будут очищать - то есть те, к которым у вас есть прямая ссылка . Например, предположим, что у вас есть класс, который имеет FileStream
переменную-член. Вы хотите реализовать IDisposable
, чтобы вы могли закрыть поток как можно скорее, если вызывающий абонент помнит - но если они не не забудут вызвать Dispose()
, поток станет пригодным для сбора мусора в то же время, как ваш объект. Поверьте, что FileStream
имеет соответствующий финализатор (или ссылку на что-то еще с финализатором и т. Д.) Вместо того, чтобы пытаться очистить его в вашем собственном финализаторе.
Начиная с .NET 2.0, с классом SafeHandle , невероятно редко требуется для вашего собственного финализатора.