Как вы думаете, какой лучший ответ на интервью на такой вопрос?
Я думаю, что не нашел копию этого здесь, если есть, пожалуйста, дайте ссылку.
Как вы думаете, какой лучший ответ на интервью на такой вопрос?
Я думаю, что не нашел копию этого здесь, если есть, пожалуйста, дайте ссылку.
Другой способ взглянуть на это — вместо того, чтобы просто цитировать спецификацию, в которой говорится, что структуры не могут/не имеют деструкторов — подумайте, что произойдет, если спецификация будет изменена так, чтобы они имели — или, скорее, давайте зададим вопрос: могут ли мы догадываемся, почему разработчики языка вообще решили не разрешать структурам иметь «деструкторы»?
(Не зацикливайтесь на слове «деструктор» здесь; мы в основном говорим о волшебном методе для структур, который вызывается автоматически, когда переменная выходит за пределы области видимости. Другими словами, языковая функция аналогична деструкторам C++. )
Первое, что нужно понять, это то, что мы не заботимся об освобождении памяти. Независимо от того, находится ли объект в стеке или в куче (например, структура в классе), о памяти рано или поздно позаботятся тем или иным образом; либо будучи извлеченным из стека, либо собранным. Настоящая причина наличия чего-то похожего на деструктор в первую очередь заключается в управлении внешними ресурсами — такими вещами, как дескрипторы файлов, дескрипторы окон или другие вещи, которые требуют специальной обработки, чтобы очистить их от CLR. сама не знает о.
Теперь предположим, что вы разрешаете структуре иметь деструктор, который может выполнять эту очистку. Отлично. Пока вы не поймете, что когда структуры передаются в качестве параметров, они передаются по значению: они копируются. Теперь у вас есть две структуры с одинаковыми внутренними полями, и они обе попытаются очистить один и тот же объект. Сначала произойдет один, и поэтому код, который впоследствии использует другой, начнет загадочным образом давать сбой... а затем его собственная очистка потерпит неудачу (надеюсь! - в худшем случае он может успешно очистить какой-то другой случайный ресурс - это может случаются, например, в ситуациях, когда значения дескриптора используются повторно.)
Возможно, вы могли бы сделать особый случай для структур, которые являются параметрами, чтобы их «деструкторы» не запускались (но будьте осторожны — теперь вам нужно помнить, что при вызове функции всегда внешний тот, кто «владеет» фактическим ресурсом - так что теперь некоторые структуры немного отличаются от других...) - но тогда у вас все еще есть эта проблема с обычными структурными переменными, где одна может быть назначена другой, создавая копию.
Возможно, вы могли бы обойти это, добавив специальный механизм в операции присваивания, который каким-то образом позволяет новой структуре согласовывать владение базовым ресурсом с его новой копией — возможно, они совместно используют его или напрямую передают право собственности от старого к новому — но теперь вы По сути, вы отправились в страну C++, где вам нужны конструкторы копирования, операторы присваивания и добавлено множество тонкостей, ожидающих, чтобы поймать в ловушку ничего не подозревающего программиста-новичка. И имейте в виду, что весь смысл C# состоит в том, чтобы максимально избежать такой сложности в стиле C++.
И, чтобы сделать ситуацию немного более запутанной, как указал один из других ответов, структуры не просто существуют как локальные объекты. С местными масштабы хороши и четко определены; но структуры также могут быть членами объекта класса. Когда в этом случае должен вызываться «деструктор»? Конечно, вы можете сделать это, когда класс контейнера будет завершен; но теперь у вас есть механизм, который ведет себя по-разному в зависимости от того, где находится структура: если структура является локальной, она срабатывает сразу в конце области видимости; если структура находится внутри класса, она запускается лениво... Поэтому, если вы действительно заботитесь о том, чтобы какой-то ресурс в одной из ваших структур очищался в определенное время, и если ваша структура может оказаться членом class, вам, вероятно, понадобится что-то явное, например IDisposable/using(), в любом случае, чтобы убедиться, что у вас есть все основания.
Так что, хотя я не могу претендовать на то, чтобы говорить от имени разработчиков языка, я могу довольно точно предположить, что одна из причин, по которой они решили не включать такую функцию, заключается в том, что это была бы куча червей, и они хотели, чтобы C# был достаточно простым. .
От Джона Джаггера:
«У структуры не может быть деструктора. Деструктор — это просто замаскированное переопределение object.Finalize
, а структуры, являющиеся типами значений, не подлежат сборке мусора».
Каждый объект, кроме массивов и строк, хранится в куче таким же образом: заголовок, который дает информацию о свойствах, «связанных с объектом» (его тип, используется ли он какими-либо активными блокировками монитора, имеет ли он неподавленный Finalize
и т. д.), и его данные (имеется в виду содержимое всех полей экземпляра типа (общедоступных, частных и защищенных смешанных, с полями базового класса, появляющимися перед полями производного типа). Поскольку каждый объект кучи имеет заголовок, система может взять ссылку на любой объект и узнать, что это такое и что с ним должен делать сборщик мусора.Если в системе есть список всех объектов, которые были созданы и имеют метод Finalize
, она может проверить каждый объект в списке, посмотрите, не подавлен ли его метод Finalize
, и подействуйте на него соответствующим образом.
Структуры хранятся без заголовка; структура типа Point
с двумя целочисленными полями просто сохраняется как два целых числа. Хотя возможно иметь ref
для структуры (такая вещь создается, когда структура передается в качестве параметра ref
), код, использующий ref
, должен знать, на какой тип структуры указывает ref
, поскольку ни ref
ни сама структура не содержит эту информацию. Кроме того, объекты кучи могут быть созданы только сборщиком мусора, что гарантирует, что любой созданный объект всегда будет существовать до следующего цикла сборки мусора. Напротив, пользовательский код может сам создавать и уничтожать структуры (часто в стеке); если код создает структуру вместе с ref
для нее и передает ее ref
вызываемой подпрограмме, нет никакого способа, чтобы этот код мог уничтожить структуру (или вообще что-либо сделать, если на то пошло) до тех пор, пока вызываемая подпрограмма не вернется, поэтому struct гарантированно существует по крайней мере до тех пор, пока не завершится вызванная подпрограмма. С другой стороны, как только вызываемая подпрограмма завершает работу, переданное ей ref
должно считаться недействительным, поскольку вызывающая сторона может уничтожить структуру в любое время после этого.
Поскольку по определению деструкторы используются для уничтожения экземпляров классов, а структуры являются типами значений.
Ссылка: http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx
По словам Microsoft: "Destructors are used to destruct instances of classes."
так что немного глупо спрашивать "Почему вы не можете использовать деструктор для (чего-то, что не является классом)?" ^^