Подтвердить что ты не робот

Почему у структур не может быть деструкторов?

Каков наилучший ответ на интервью по такому вопросу, который вы думаете?

Я думаю, что я не нашел здесь этого экземпляра, если есть, пожалуйста, соедините его.

4b9b3361

Ответ 1

Еще один способ взглянуть на это - вместо того, чтобы просто указывать спецификацию, в которой говорится, что структуры не могут/не имеют деструкторов, - подумайте, что произойдет, если спецификация будет изменена так, чтобы они это сделали - вернее, спросите вопрос: можем ли мы догадаться, почему дизайнеры языка решили не позволять структурам иметь "деструкторы" в первую очередь?

(Не зацикливайтесь на слове "деструктор" здесь, мы в основном говорим о волшебном методе для структур, который автоматически вызывается, когда переменная выходит за пределы области видимости. Другими словами, языковая функция, аналогичная С++ деструкторы.)

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

Теперь предположим, что вы разрешаете структуре иметь деструктор, который может выполнить эту очистку. Хорошо. Пока вы не поймете, что когда structs передаются как параметры, они передаются по значению: они копируются. Теперь у вас есть две структуры с одинаковыми внутренними полями, и они оба попытаются очистить один и тот же объект. Сначала это произойдет, и поэтому код, который использует другой, впоследствии начнет сбой таинственным образом... и тогда его собственная очистка потерпит неудачу (надеюсь, что! - в худшем случае это может привести к удалению некоторых других случайных ресурсов - это может происходят в ситуациях, когда значения дескриптора повторно используются, например.)

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

Возможно, вы можете обойти это, добавив специальный механизм для операций присваивания, который каким-то образом позволяет новой структуре обсуждать право собственности на базовый ресурс с его новой копией - возможно, они разделяют ее или передают право собственности прямо из старого в новое - но теперь вы, по сути, отправились на С++ - землю, где вам нужны копировальные аппараты, операторы присваивания и добавили кучу тонкостей, ожидающих, чтобы уловить не знающего начинающего программиста. И имейте в виду, что вся точка С# заключается в том, чтобы как можно больше избежать сложностей такого типа С++.

И просто для того, чтобы сделать вещи более запутанными, как заметил один из других ответов, структуры не просто существуют как локальные объекты. С местными жителями область хороша и четко определена; но структуры также могут быть членами объекта класса. Когда следует вызвать "деструктор" в этом случае? Конечно, вы можете это сделать, когда класс контейнера завершен; но теперь у вас есть механизм, который ведет себя по-разному в зависимости от того, где живет структура: если структура является локальной, она запускается немедленно в конце области; если структура находится внутри класса, она запускается с лёгкостью... Поэтому, если вы действительно заботитесь о том, чтобы какой-то ресурс в одной из ваших структур был очищен в определенное время, и если ваша структура может оказаться в качестве члена класс, вам, вероятно, понадобится что-то явно вроде IDisposable/using(), чтобы убедиться, что у вас есть ваши базы.

Поэтому, хотя я не могу претендовать на то, чтобы говорить за дизайнеров языка, я могу сделать довольно хорошее предположение, что одна из причин, по которой они решили не включать такую ​​функцию, состоит в том, что это может быть банда червей, и они хотели сохранить С# достаточно простой.

Ответ 2

Из Джон Джаггер:

"Структура не может иметь деструктор. Деструктор является переопределением object.Finalize в маскировке, а структуры, являющиеся типами значений, не подлежат сборке мусора."

Ответ 3

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

Структуры сохраняются без заголовка; структура типа Point с двумя целыми полями просто сохраняется в виде двух целых чисел. Хотя возможно иметь ref для структуры (такая вещь создается, когда struct передается как параметр ref), код, который использует ref, должен знать, какой тип структуры ref указывает на то, что ни ref, ни сама структура не содержат эту информацию. Кроме того, объекты кучи могут создаваться только сборщиком мусора, что гарантирует, что любой созданный объект будет всегда существовать до следующего цикла GC. Напротив, код пользователя может создавать и разрушать структуры самостоятельно (часто в стеке); если код создает для него структуру вместе с ref и передает это ref в вызываемую подпрограмму, то нет способа, чтобы этот код мог разрушить структуру (или вообще что-либо сделать, если на то пошло) до тех пор, пока вызываемая процедура возвращается, поэтому структура, как гарантируется, будет существовать, по крайней мере, до тех пор, пока вызывается вызываемая процедура. С другой стороны, как только вызывается вызванная процедура, значение ref, которое оно было задано, должно считаться недействительным, так как вызывающий может свободно уничтожать структуру в любое время после этого.

Ответ 4

Becuase по определению деструкторы используются для уничтожения экземпляров классов, а структуры - это типы значений.

Ссылка: http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx

Своими словами Microsoft: "Destructors are used to destruct instances of classes.", так что немного глупо спросить: "Почему вы не можете использовать деструктор (что-то, что не является классом)?" ^^