2012-06-01 1 views
0

У меня есть класс C#, который реализует IDisposable и в моей реализации Dispose(). Я вызываю Dispose() в подпроектах, которые также реализуют IDisposable.Должен ли я сделать что-нибудь особенное в деструкторе класса, который реализует IDisposable?

Как насчет деструктора того же класса? Должен ли я делать что-то особенное там?

+0

Обычно вам не требуется реализовать деструктор. Я верю только в том случае, если вы напрямую используете неуправляемые ресурсы. – Oded

+0

О IDisposable и finalizers (поскольку нет _destructors_ per se, как на C++), вы можете прочитать [этот удивительный ответ] (http://stackoverflow.com/a/538238/1180426) –

+0

возможный дубликат [Правильный использование интерфейса IDisposable] (http://stackoverflow.com/questions/538060/proper-use-of-the-idisposable-interface) – sloth

ответ

0

Нет, до тех пор, пока вы освобождаете любые ресурсы в реализации Dispose, вы в порядке. Корпорация Майкрософт рекомендует использовать интерфейс IDisposable с помощью инструкции using(), чтобы приложение сразу вызывало удаление, когда объект выходит из области видимости. Похоже, вы делаете все хорошо - просто убедитесь, что вы пытаетесь использовать using() при использовании этой реализации.

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

Update:

Похож Theres причины для создания деструктора тоже, как кто-то писал в своем комментарии :)

вы узнаете что-то новое каждый день здесь: D

0

Я думаю, что вы имеете в виду финализатор вместо деструктор.

Обратите внимание, что финализатор довольно необычен. Конечно, неверно, что каждый одноразовый объект должен иметь финализатор. Обычно для объектов, которые управляют не управляемыми ресурсами (т. Е. Теми, которые не контролируются CLR), может потребоваться финализатор.

Если вам определенно нужен финализатор, вы должны позвонить GC.SuppressFinanlize в свой метод размещения. Из документов для implementing a Dispose method:

Способ Dispose должен вызывать метод SuppressFinalize для объекта он выбывает. Если объект в настоящий момент находится на этапе завершения , SuppressFinalize не позволяет его методу Finalize быть вызванным . Помните, что выполнение метода Finalize дорого стоит . Если ваш метод Dispose уже выполнил работу по очистке объекта , тогда сборщик мусора не должен вызывать метод Finalize объекта.

Для примера образец, который включает финализатор, см. В GC.SuppressFinanlize documentation.

+0

Небольшая заметка о терминологии: «деструктор» в C# является синтаксическим элементом, который направляет компилятор для создания метода переопределения для 'Object.Finalize', который обертывает поставляемый код в блок' try'/'finally' вместе с вызовом' base.Finalize() '. В то время как я сильно не люблю терминологию и синтаксис, и не знаю, почему бы не просто разрешить программам C# переопределять «Finalize», я не знаю ни одного термина, кроме «деструктора», чтобы описать этот конкретный элемент синтаксиса C#. С другой стороны, деструкторы не зарегистрированы в GC - финализаторы. Таким образом ... – supercat

+0

... если кто-то хочет быть супер-правильным в отношении терминологии, вы можете заметить, что деструкторы C# используются для реализации финализаторов, а так как финализаторы обычно не нужны, а иногда и вредны, деструкторы тоже. – supercat

1

Синтаксис 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 (непредсказуемые сбои), если не обрабатываться отлично на на каждом шаге цепочки наследования. Если базовый класс не предназначен для поддержки надежной очистки финализации, добавление финализатора к производному классу может привести к поломке кода, который в противном случае сработал бы.

Смежные вопросы