В чем разница между деструктором и методом завершения?
Сегодня будет еще один диалог и еще один эпизод из моей постоянной рубрики «в чем разница?».
В чем разница, если она вообще существует, между «деструктором» ( destructor ) и «методом завершения» (finalizer)?
Оба понятия являются механизмом очистки ресурсов после того, как в них пропадает необходимость. Когда меня спросили об этом, я сначала подумал, что между этими понятиями нет разницы. Однако небольшой поиск по Википедии показал различия; термин «деструктор» обычно означает детерминированный вызов методаочистки, в то время как «метод завершения» вызывается по требованию сборщика мусора.
Означает ли это, что в спецификации C# термин «деструктор» используется некорректно?
Да, согласно этому определению, в спецификации C# допущена ошибка. То, что в спецификации называется «деструктором» на самом деле является «методом завершения», а то, что мы называем вызовом метода “Dispose()” при выходе из блока “using”, по сути, является «деструктором».
В спецификации CLI метод завершения называется правильно.
Почему авторы спецификации C# допустили такую ошибку?
Я не знаю, но могу предположить. У меня есть две догадки.
Догадка №1 заключается в том, что 12 мая 1999 года еще не было статьи в Википедии ясно описывающей тонкие различия между этими двумя понятиями. Потому что не было тогда еще Википедии. Помните то далекое прошлое, когда не было Википедии? Темные времена, дружище. Ошибка просто заключается в невинном заблуждении, что эти два термина равнозначны.
Черт возьми! Я думаю, что 12 мая 1999 года эти термины значили одно и то же, а различия в определениях появилась позже, когда стало очевидно, что нужно различать методы принудительной/детерминированной и ленивой/недетерминированной очистки ресурсов. Если кто-то лучше меня знает историю того времени, не стесняйтесь, присоединяйтесь к дискуссии.
Предположение №2 заключается в том, что 12 мая 1999 года, комитет по проектированию языка C# хотел оставить возможность, чтобы деструктор был реализован не только как метод завершения CLR. Т.е. «деструктор», как концепция языка программирования C#, не обязан в точности соответствовать концепции «метода завершения» CLR.
При одновременном проектировании языка программирования и инфраструктуры (framework), на которой основан этот язык, порой возникает желание защитить себя от разрушительных изменений подсистем на поздних стадиях. Один из способов добиться этого – преднамеренное разделение имен.
Что у вас за одержимость 12 мая 1999 года?
Заметка комитета по стандартизации языка от 12 мая 1999 года:
”Мы собираемся использовать термин «деструктор» в качестве названия метода, который будет выполняться при освобождении объекта. Деструкторы могут быть только у классов, структуры содержать деструкторы не могут. В отличие от С++, явный вызов деструктора невозможен. Время вызова деструктора не определено – вы не можете точно знать, когда деструктор будет вызван, но вы можете точно сказать, что он будет выполнен после освобождения всех ссылок на объект. В случае иерархии наследования деструкторы вызываются в порядке от самых дальних наследников к ближним. Нет необходимости (и не существует способа) для класса наследника явно вызвать деструктор базового класса. Компилятор C# компилирует деструкторы в соответствующее представление для CLR. Для данной версии это, вероятно, означает метод завершения экземпляра, указанный в метаданных.”
Обратите внимание, что это подтверждает мое предположение о том, что команда проектирования языка пыталась оградить себя от привязки к конкретному термину CLR.
Comments
Anonymous
June 01, 2010
В случае иерархии наследования деструкторы вызываются в порядке от самого базового класса к производным. The destructors in an inheritance chain are called in order, from most descendant to least descendant. Кажется перевод инвертировал смысл.Anonymous
August 20, 2010
вроде в статье все верно: как раз from most descendant to least descendant означает от наиболее удаленных до наименее удаленных. иметтся в виду удаленных от базового класса. то же самое и в с++