Ответ 1
Что произойдет с объектами, вызываемыми GC.SuppressFinalize? Я понимаю, что это означает, что GC не будет вызывать финализатор таких объектов (деструктор), если да, когда эти объекты будут действительно разрушены? в противном случае произойдет ли утечка памяти?
У вас есть непонимание того, для чего предназначена финализация. Завершение - очистка ресурсов, которые не управляются.
Предположим, что у вас есть объект ссылочного типа, который содержит целое поле. Это целочисленное поле просто является дескриптором файла, который был получен путем вызова неуправляемого кода для открытия файла.
Поскольку какая-либо другая программа может захотеть получить доступ к этому файлу, вежливо закрыть файл как можно скорее. Но среда выполнения .NET не знает, что это целое имеет какое-то особое значение для операционной системы. Это просто целое число.
Как вы обычно решаете эту проблему, вы отмечаете объект как реализующий IDisposable, а затем вы вызываете "Dispose" на объект, как только вы закончите с ним. Затем ваша реализация "Dispose" закрывает файл.
Обратите внимание, что здесь ничего особенного не происходит. Это просто соглашение о том, что метод, который очищает неуправляемый ресурс, называется "Dispose", а объект, который должен быть удален, реализует IDisposable. Мусорная коллекция ничего не знает об этом.
Итак, теперь возникает проблема: что, если кто-то забывает вызывать Dispose? Сохраняется ли файл навсегда? (Очевидно, что файл будет закрыт, когда процесс завершится, но что делать, если процесс длится долго?)
Чтобы решить эту проблему, вы используете финализатор. Как это работает?
Когда объект собирается собирать мусор, сборщик мусора проверяет его, имеет ли он финализатор. Если это так, то вместо сбора мусора он помещает его в очередь финализатора. В какой-то неопределенной точке в будущем выполняется поток, который проверяет очередь и вызывает специальный метод "Finalize" для каждого объекта. После этого объект удаляется из очереди финализации и помечен как "эй, я уже был финализирован". Теперь объект снова доступен для сбора, поэтому сборщик мусора в конечном итоге запускает и собирает объект, не помещая его в очередь финализации.
Ясно, что "Finalize" и "Dispose" часто нужно делать то же самое.
Но теперь возникает другая проблема. Предположим, вы выбрали объект. Теперь его не нужно дорабатывать. Завершение является дорогостоящим; он держит мертвый объект живым намного дольше, чем нужно. Поэтому, традиционно, когда вы размещаете объект, реализация Dispose не только закрывает неуправляемый ресурс, но и отмечает объект как "этот объект уже завершен, не завершайте его снова". Таким образом, он обманывает сборщик мусора, чтобы не помещать объект в очередь финализации.
Итак, давайте ответим на ваши конкретные вопросы:
Что произойдет с объектами, которые вызывается GC.SuppressFinalize?
Когда объект мертв, сборщик мусора просто восстанавливает память объекта, не помещая объект в очередь финализатора.
Я понимаю, что это означает, что GC не будет вызывать финализацию таких объектов
GC никогда не вызывает финализатор. Финализатор - это единственное, что вызывает финализаторы.
когда эти объекты будут действительно разрушены?
Неясно, что вы подразумеваете под "разрушенным". Если вы имеете в виду "когда будут финализаторы?" ответ "никогда", потому что вы сказали подавить финализацию. Если вы имеете в виду "когда будет восстановлена память в управляемой куче?", Ответ будет "как только объект будет идентифицирован как мертвый сборщик мусора". Это произойдет раньше обычного, потому что объект не будет сохранен в очереди финализатора.