Сборка мусора в .net имеет два аспекта: финализация и уничтожение. Когда объект, имеющий финализатор, создан, он добавляется в специальный список, который я назову «финализируемым» списком. Каждый раз, когда запускается сборщик мусора, он идентифицирует объекты, которые ничем не достижимы, те, которые доступны только из списка «финализируемых» или объектов в нем, и те, которые доступны чем-то другим, не проходя через список «финализируемых». Объекты, которые вообще недоступны, уничтожаются. Те, которые доступны только из «финализируемого» списка или объектов в нем, удаляются из этого списка и помещаются в список «финализировать сейчас». Объекты, которые достижимы чем-то кроме «финализируемого» списка, выживают в GC. Пока GC сортирует объекты по этим трем категориям, выполнение всего кода останавливается. После завершения GC выполнение кода возобновляется, и специальный поток запускает метод Finalize всех объектов в списке «Завершить сейчас».
Обратите внимание, что объекты в списке "завершить сейчас", а также любые объекты, на которые они ссылаются, не будут собираться мусором, пока они находятся в этом списке; они могут получить право на сборку мусора только после запуска финализатора. Как только они перестают быть в списке «завершить сейчас», они могут снова получить право на сбор.