Синтаксис C# destructor позволяет компилятору переопределить Object.Finalize()
. Класс, который переопределяет Object.Finalize()
, как утверждается, имеет «финализатор»; все такие объекты помещаются в специальный список под названием «Конечная очередь» (термин «очередь», возможно, немного странный, поскольку список не имеет семантически релевантного упорядочения) и помечен как «finalizable». Когда выполняется сбор мусора, система начинается с пометки всех объектов, к которым существуют прямые или косвенные сильные ссылки вне очереди финализации. Затем система проверяет каждый финализируемый объект, чтобы проверить, не помечен ли он еще. Если этого не произошло, он будет помечен как «не окончательный», но будет добавлен в очередь, называемую «freachable [eff-достижимая] очередь».Наконец, система будет отмечать все объекты в freachable queue как «живые», отбрасывать все немаркированные объекты и - если freachable queue не пуст - отправьте поток, чтобы начать вызов Finalize
по всем содержащимся в нем элементам. Обратите внимание, что объекты, находящиеся в «freachable queue», и каждый объект, к которому они имеют сильные ссылки, будут считаться «живыми», пока не будет запущен их метод Finalize()
; поскольку они будут отмечены как «не подлежащие окончательной доработке», после этого они будут иметь право на сбор мусора, если только они не были перемаркированы как «финализируемые», или сильная ссылка на них была сохранена в живом объекте.
Обратите внимание, что в «деструктор» или «финализации» делает ускорить разрушение объекта - вместо этого, он даст объекты, которые бы были уничтожены помилование запустить их Finalize()
метод (который, для C# программ, в свою очередь будет запускать код в деструкторе). Это может быть полезно, если объект с финализатором знает о чем-то, что (1) должно произойти до конца юниверса, (2) никакой другой объект не собирается делать, и (3) можно безопасно сделать в пределах произвольного и неизвестный контекст нитей. Обратите внимание, что финализатор редко используется для вызова IDisposable.Dispose
на другие объекты. Если такие объекты могут обрабатываться, если они удалены из произвольных контекстов потоков, они могут, вероятно, завершить свою работу (поэтому их удаление не будет соответствовать требованию № 2); если они не могут справиться с удалением из произвольных контекстов потоков, они не могут быть удалены в финализаторе (требование № 3).
Кстати, Microsoft на ранних стадиях развития .net, казалось, думали, что классы, которые реализуют IDisposable
, но не имеют финализаторы, должны обеспечить таким образом производные классы могут добавлять финализаторы, и они продолжают рекомендовать Dispose
шаблон, который делает скидку на это. Хотя иногда бывает полезно, чтобы производный класс имел финализатор «тревожного звонка», который генерирует какое-то предупреждение, если он вызван на объект, который не был удален, я бы предположил, что класс, полученный из нетривиального класс, который не имеет финализатора, не должен пытаться выполнять очистку в методе finalize или деструкторе. Завершение включает в себя некоторые сложные угловые случаи, которые могут вызвать Heisenbugs (непредсказуемые сбои), если не обрабатываться отлично на на каждом шаге цепочки наследования. Если базовый класс не предназначен для поддержки надежной очистки финализации, добавление финализатора к производному классу может привести к поломке кода, который в противном случае сработал бы.
Обычно вам не требуется реализовать деструктор. Я верю только в том случае, если вы напрямую используете неуправляемые ресурсы. – Oded
О IDisposable и finalizers (поскольку нет _destructors_ per se, как на C++), вы можете прочитать [этот удивительный ответ] (http://stackoverflow.com/a/538238/1180426) –
возможный дубликат [Правильный использование интерфейса IDisposable] (http://stackoverflow.com/questions/538060/proper-use-of-the-idisposable-interface) – sloth