Методы удаления, финализаторы и деструкторы с ироническим именем в C # существуют потому, что многие объекты просят другие объекты делать что-то от их имени до дальнейшего уведомления (как правило, предоставляя исключительное использование чего-то вроде файла, области памяти, потока связи, аппаратное устройство, дескриптор GDI и т. д.); если объект, выдающий такой запрос, исчезнет без того, чтобы другие объекты не знали, что их услуги больше не требуются, все, что было отложено от имени оставленного объекта, останется бесполезно недоступным.
Метод IDisposable.Dispose
обеспечивает хороший последовательный способ сообщить объекту, что от него больше не будет требоваться что-либо делать, потребуется помощь других лиц, и что любые другие объекты, которые делают что-либо от его имени, должны быть уведомлены прекратить это делать. Если IDisposable.Dispose
вызывается правильно, объекты могут минимизировать степень, в которой внешние объекты должны действовать от их имени.
К сожалению, по разным причинам (большинство из них легко избежать; некоторые нет), объекты иногда оставляются без вызова IDisposable.Dispose
. Это приведет к тому, что сторонним организациям придется бесполезно продолжать действовать, по крайней мере, некоторое время, от имени оставленных объектов. Чтобы не допустить, чтобы внешние сущности действовали вечно от имени внешних сущностей, система может уведомлять объекты о том, что они были оставлены, что дает им возможность информировать внешние сущности об этом факте. Всякий раз, когда создается объект, класс которого переопределяет Object.Finalize
, он будет помещен в специальный список объектов, которые хотят получать уведомления, если они были оставлены. Само по себе наличие в этом списке недостаточно для того, чтобы объект считался «живым», но перед тем, как сборщик мусора удалит мертвые объекты из памяти, он проверит, находятся ли они в списке уведомлений перед уничтожением. Все мертвые объекты, которые есть в списке, будут перемещены из списка объектов, запрашивающих уведомление, если / когда они будут оставлены, в список объектов, нуждающихся в уведомлении о том, что они имеют . Размещение в этом втором списке приведет к тому, что мертвые объекты и любые объекты, на которые они ссылаются , снова будут считаться «живыми», по крайней мере, до тех пор, пока не будет выполнено уведомление. Однако когда они перемещаются во второй список, они удаляются из первого списка, так что, если впоследствии они обнаружат, что они снова мертвы, они будут удалены из памяти без дальнейшего уведомления.
После завершения сборки мусора, если какие-либо объекты находятся в списке объектов, о которых необходимо уведомить об отказе, система вызовет метод Object.Finalize
для каждого такого объекта. Как правило, после вызова Object.Finalize
для такого объекта больше не будет корневых ссылок на него, и он исчезнет при следующей сборке мусора. Однако возможно возрождение объектов.
В vb.net и, насколько мне известно, в большинстве языков .net один переопределяет Object.Finalize
, просто объявляя переопределение обычным способом. По какой-то причине создатели C # решили запретить это. Вместо этого в C # необходимо использовать языковую структуру, по иронии судьбы называемую «Разрушитель», чтобы переопределить Finalize
, чтобы объекты, которые были найдены как оставленные, не были уничтожены без уведомления, а вместо этого были заданы шанс навести порядок.
В реальной операции Object.Finalize
есть много хитрых морщин, и лучше избегать полагаться на это, кроме случаев, когда это абсолютно необходимо. Иронически названные «деструкторы» на самом деле не разрушают объекты, а задерживают их разрушение. Вызов GC.SuppressFinalize()
для объекта удалит его из списка объектов, запрашивающих уведомление, когда они будут оставлены; при условии, что Dispose
вызывается для объекта, и он, в свою очередь, вызывает GC.SuppressFinalize()
как свою последнюю операцию, нет особого вреда в том, что объект переопределил Finalize
или объявил "деструктор" ", но в общем случае лучше переопределить Finalize
(или объявить" деструкторы ") в относительно простых классах.