Ни один объект не может быть собран мусором, пока он распознается как существующий. Объект будет существовать в .NET до тех пор, пока существует какая-либо ссылка на него или у него есть зарегистрированный финализатор, и он перестанет существовать, когда ни одно из условий не будет применено. Ссылки в объектах будут существовать до тех пор, пока существуют сами объекты, а ссылки в автоматических переменных будут существовать до тех пор, пока существуют какие-либо средства, с помощью которых они будут наблюдаться. Если сборщик мусора обнаружит, что единственные ссылки на объект без зарегистрированного финализатора содержатся в слабых ссылках, эти ссылки будут уничтожены, что приведет к прекращению существования объекта. Если сборщик мусора обнаруживает, что единственные ссылки на объект с зарегистрированным финализатором хранятся в слабых ссылках, то любые слабые ссылки, свойство «воскресение трека» которых имеет значение false, ссылка на объект будет помещена в строго укоренившийся список объектов. нуждающихся в «немедленной» финализации, и финализатор будет незарегистрирован (что позволит ему прекратить свое существование, если и когда финализатор достигнет точки выполнения, где вообще не будет никакой ссылки на объект).
Обратите внимание, что некоторые источники путают запуск финализатора объекта с сборкой мусора, но объект, чей финализатор запущен, гарантированно будет продолжать существовать, по крайней мере, столько времени, сколько потребуется для выполнения этого финализатора, и может продолжать существовать бесконечно если какие-либо ссылки на него существуют, когда финализатор заканчивает выполнение.
В вашем примере есть три сценария, которые могут применяться в зависимости от того, что CountThings
делает с переданной ссылкой:
Если CountThings
нигде не хранит копию ссылки, или любые копии ссылок, которые он хранит, перезаписываются до того, как перезаписывается input
, то он прекращает свое существование, как только input
перезаписывается или перестает существовать [переменные автоматической продолжительности могут перестать существовать каждый раз, когда компилятор определяет, что их значение больше не будет соблюдаться].
Если CountThings
хранит копию ссылки где-то, которая продолжает существовать после ее возврата, а последняя существующая ссылка удерживается чем-то иным, чем слабая ссылка, тогда объект прекратит существование, как только последняя ссылка уничтожена.
Если последняя существующая ссылка, массив в конечном итоге удерживается в слабой ссылке, массив будет продолжать существовать до первого цикла GC, где это имеет место, после чего слабая ссылка будет очищена, вызывая массив перестать существовать. Обратите внимание, что отсутствие неслабых ссылок на массив будет актуально только тогда, когда происходит цикл GC. Для программы возможно (и не очень редко) сохранять копию ссылки в WeakReference
, ConditionalWeakTable
или другом объекте, содержащем некоторую форму слабой ссылки, уничтожать все другие копии, а затем считывать слабую ссылка для создания неслабой копии ссылки до следующего цикла GC. Если это произойдет, система не будет ни знать, ни заботиться о том, что было время, когда существовали неслабые копии ссылки. Однако, если цикл GC происходит до того, как ссылка будет считана, тогда код, который позже исследует слабую ссылку, найдет ее пустой.
Ключевое наблюдение заключается в том, что, хотя финализаторы и слабые ссылки немного усложняют ситуацию, единственный способ, которым GC уничтожает объекты, заключается в недействительности слабых форм ссылок. Что касается GC, то единственными типами хранилищ, которые существуют, когда система фактически не выполняет цикл GC, являются те, которые используются существующими объектами, те, которые используются для внутренних целей .NET, и области хранения, которые доступны для удовлетворить будущие ассигнования. Если объект создан, занимаемое им хранилище перестает быть областью хранилища, доступной для будущих выделений. Если впоследствии объект перестает существовать, хранилище , в котором содержался объект, также прекращает существовать в любой форме, о которой GC знает до следующего цикла GC. Следующий цикл GC не уничтожит объект (который уже прекратил свое существование), но вместо этого добавит хранилище, в котором он находился, обратно в список областей, доступных для добавления будущих выделений (в результате чего это хранилище снова будет существовать) .