Что означает тильда перед именем функции в C #?

165

Я смотрю на некоторый код, и он имеет следующее утверждение:

~ConnectionManager()
{
    Dispose(false);
}

Класс реализует IDisposableинтерфейс, но я не знаю, является ли это частью того, для чего используется тильда (~).

Кит Сирмонс
источник

Ответы:

214

~ деструктор

  1. Деструкторы вызываются автоматически и не могут быть вызваны явно.
  2. Деструкторы не могут быть перегружены. Таким образом, класс может иметь не более одного деструктора.
  3. Деструкторы не наследуются. Таким образом, у класса нет деструкторов, кроме того, который может быть объявлен в нем.
  4. Деструкторы нельзя использовать со структурами. Они используются только с классами. Экземпляр становится пригодным для уничтожения, когда ни один код больше не может использовать экземпляр.
  5. Выполнение деструктора для экземпляра может произойти в любое время после того, как экземпляр станет пригодным для уничтожения.
  6. Когда экземпляр уничтожается, деструкторы в его цепочке наследования вызываются по порядку от большинства производных к наименее производным.

Доработка

В C # метод Finalize выполняет операции, которые выполняет стандартный деструктор C ++. В C # вы не называете его Finalize - вы используете синтаксис деструктора C ++, помещая символ тильды (~) перед именем класса.

Dispose

Предпочтительно располагать объекты в методе Close()или, Dispose()который может быть явно вызван пользователем класса. Finalize (деструктор) вызывается GC.

Интерфейс IDisposable сообщает миру, что ваш класс хранит ресурсы, которые необходимо утилизировать, и предоставляет пользователям способ их освобождения. Если вам нужно реализовать финализатор в вашем классе, ваш метод Dispose должен использовать GC.SuppressFinalize()метод, чтобы гарантировать, что финализация вашего экземпляра подавлена.

Что использовать?

Недопустимо явно вызывать деструктор. Ваш деструктор будет вызван сборщиком мусора. Если вы обрабатываете драгоценные неуправляемые ресурсы (например, файловые дескрипторы), которые хотите закрыть и утилизировать как можно быстрее, вам следует реализовать интерфейс IDisposable.

Патрик Дежарден
источник
3
Я не знаю, как это было в прошлом. Но теперь деструкторы наследуются. Проверьте эту ссылку для получения дополнительной информации (см. Пример в конце): msdn.microsoft.com/en-us/library/66x5fx1b.aspx
RononDex
1
@RononDex, пункт 3 самой страницы, на которую вы ссылаетесь, гласит: «Финализаторы не могут быть унаследованы» , что противоречит вашему комментарию. По общему признанию, это немного сбивает с толку, потому что, хотя они не могут быть унаследованы, « Finalizeметод вызывается рекурсивно для всех экземпляров в цепочке наследования, от самого производного до наименее производного» . Обратите внимание, что это не то же самое поведение, которое вы бы получили от наследуемых деструкторов.
Марк Эмери
@MarkAmery ах, я вижу, поэтому в основном они вызываются в обратном порядке по сравнению с чем-то, что наследуется?
RononDex
45

Это финализатор . Если честно, очень редко нужно писать финализатор. Вам действительно нужно написать только один, если:

  • У вас есть прямой доступ к неуправляемому ресурсу (например, через IntPtr), и вы не можете использовать SafeHandleего, что облегчает
  • Вы реализуете IDisposableв классе, который не запечатан. (Я предпочитаю запечатывать классы, если они не предназначены для наследования.) В таких случаях финализатор является частью канонического шаблона Dispose.
Джон Скит
источник
9

Он используется для указания деструктора для класса.

ториальную
источник
12
Они оба правильные, в зависимости от того, какую C # спецификацию вы прочитали. Самая последняя версия MS (унифицированная C # 3.0) называет их деструкторами (например, раздел 10.13), но спецификация ECMA называет их финализаторами.
Джон Скит
@ 1800INFORMATION: синтаксический элемент по праву называется деструктором. Если у класса есть деструктор, компилятор C # автоматически сгенерирует финализатор, который включает обычно бесполезный try/finallyблок, который гарантирует, что Finalizeбудет вызван родительский метод. Большинство вещей, которые верны для деструкторов, верны и для финализаторов, и наоборот, но слова означают немного разные вещи.
суперкат
4

Как и в C ++, это деструктор; однако в C # вы не вызываете его явно, он вызывается, когда объект собирается.

Сантьяго Палладино
источник
1

~ обычно представляет собой деконструктор. который запускается прямо перед тем, как объект умирает.

Вот описание C # деконструкторов я нашел

stephenbayer
источник
4
правильный термин должен быть деструктором / финализатором, а не деконструктором. Деконструктор означает синтаксис для деконструкции конструктора.
Эриаван Кусумавардхоно