Когда я должен создать деструктор? - PullRequest
174 голосов
/ 04 февраля 2011

Например:

public class Person
{
    public Person()
    {
    }

    ~Person()
    {
    }
}

Когда мне вручную создавать деструктор?Когда вам нужно было создать деструктор?

Ответы [ 7 ]

223 голосов
/ 04 февраля 2011

ОБНОВЛЕНИЕ: Этот вопрос был темой моего блога в мае 2015 года .Спасибо за отличный вопрос!Смотрите в блоге длинный список лжи, о которых обычно думают люди о финализации.

Когда мне вручную создавать деструктор?

Почти никогда.

Обычно один создает деструктор только тогда, когда ваш класс держится за какой-то дорогой неуправляемый ресурс, который необходимо очистить, когда объект исчезнет.Лучше использовать одноразовый шаблон для обеспечения очистки ресурса.Деструктор, по сути, является гарантией того, что, если потребитель вашего объекта забудет его утилизировать, ресурс все равно будет очищен.(Возможно.)

Если вы создаете деструктор , будьте предельно осторожны и поймите, как работает сборщик мусора .Деструкторы действительно странные :

  • Они не работают в вашем потоке;они бегут в своей собственной нити.Не вызывайте взаимоблокировок!
  • Необработанное исключение, создаваемое деструктором, является плохой новостью.Это на своей собственной нити;кто его поймает?
  • Деструктор может быть вызван для объекта после конструктора, но до конструктора.Правильно написанный деструктор не будет полагаться на инварианты, установленные в конструкторе.
  • Деструктор может «воскресить» объект, снова оживив мертвый объект.Это действительно странно.Не делай этого.
  • Деструктор никогда не сможет бежать;Вы не можете полагаться на объект, когда-либо запланированный для завершения.Это , вероятно, будет, но это не гарантия.

Почти все, что обычно верно, не является правдой в деструкторе.Будьте очень, очень осторожны.Написание правильного деструктора очень сложно.

Когда вам нужно было создать деструктор?

При тестировании части компилятора, которая обрабатывает деструкторы.Мне никогда не приходилось делать это в рабочем коде.Я редко пишу объекты, которые манипулируют неуправляемыми ресурсами.

17 голосов
/ 04 февраля 2011

Он называется «финализатором», и вы обычно должны создавать его только для класса, чье состояние (т. Е. Поля) включает неуправляемые ресурсы (т. Е. Указатели на дескрипторы, полученные с помощью вызовов p / invoke). Однако в .NET 2.0 и более поздних версиях существует более эффективный способ очистки неуправляемых ресурсов: SafeHandle . Учитывая это, вам больше не нужно писать финализатор снова.

8 голосов
/ 04 февраля 2011

Он вам не нужен, если ваш класс не поддерживает неуправляемые ресурсы, такие как дескрипторы файлов Windows.

3 голосов
/ 04 февраля 2011

Если у вас есть неуправляемые ресурсы, и вам нужно убедиться, что они будут очищены, когда ваш объект исчезнет. Хорошим примером могут быть COM-объекты или обработчики файлов.

3 голосов
/ 04 февраля 2011

Он называется деструктором / финализатором и обычно создается при реализации шаблона Disposed.

Это запасное решение, когда пользователь вашего класса забывает вызвать Dispose, чтобы убедиться, что (в конечном итоге) ваши ресурсыосвобождается, но у вас нет никаких гарантий относительно того, когда вызывается деструктор.

В этом вопросе переполнения стека принятый ответ правильно показывает, как реализовать шаблон удаления.Это необходимо только в том случае, если ваш класс содержит какие-либо неопределяемые ресурсы, которые сборщик мусора не может очистить сам.

Хорошей практикой является не реализовывать финализатор, не предоставив пользователю класса возможность вручнуюУтилизация объекта для немедленного освобождения ресурсов.

2 голосов
/ 22 октября 2013

Я использовал деструктор (только для целей отладки), чтобы посмотреть, удалялся ли объект из памяти в области действия приложения WPF. Я был не уверен, действительно ли сборщик мусора удалял объект из памяти, и это был хороший способ проверить.

0 голосов
/ 04 февраля 2011

Деструкторы предоставляют неявный способ освобождения неуправляемых ресурсов, инкапсулированных в вашем классе, они вызываются, когда к нему обращается GC, и неявно вызывают метод Finalize базового класса.Если вы используете много неуправляемых ресурсов, лучше предоставить явный способ освобождения этих ресурсов через интерфейс IDisposable.См. Руководство по программированию на C #: http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx

...