ГХ может собрать любой объект, для которого он может доказать , что он не имеет значения для приложения. Можно подумать об этом следующим образом: объекты выделяются навсегда , но реализации разрешено восстанавливать память, если она гарантирует, что вы ее не заметите.
В вашем примере, в первом GC.Collect()
первая ссылка на объект была записана в r1
, а r1
- статическая переменная, таким образом, как-то «постоянная». С точки зрения GC, практически любой код может использовать эту статическую переменную, поэтому GC не может гарантировать, что первый объект не будет использоваться. Поэтому он не может собрать это. Второй объект, с другой стороны, записывается в переменную local . Локальная переменная ограничена кодом метода (он исчезает при выходе из метода), и GC может заметить, что r2
больше не будет использоваться (GC нужно только смотреть на метод, а не весь код, поэтому это часть того, что GC может разумно сделать). Поэтому GC может собрать второй объект (здесь нет никаких обязательств).
Третий объект все еще будет использоваться после первого GC.Collect()
: вызывается его метод ToString()
. Следовательно GC не должен собирать это. Тем не менее, вполне возможно, что виртуальная машина замечает, что это истинный экземпляр Object
(не любой другой класс), включает в себя вызов ToString()
и далее заключает, что весь вызов ToString()
является сложным способом ничего не делать (нет видимого результата). Таким образом, GC может быть в состоянии собрать третий объект и вообще пропустить вызов ToString()
.
Конечно, GC также может не собирать вещи. Весь смысл GC заключается в том, что он работает "за сценой", не влияя на выполнение кода (это не совсем верно при наличии финализации, но это дополнительный уровень сложности, который не следует предполагать, пока вы не освоите основы) .
Статья Уилсона действительно необходима для чтения всем, кто хочет понять, что делает сборка мусора.