Что такое метод финалайз (finalize) в C# и можем ли мы его вызвать
Что проверяют
Понимаете ли вы разницу между детерминированным освобождением и работой сборщика мусора. В формулировке ловушка: метода с таким именем в C# писать нельзя, и сильный ответ начинается с уточнения терминов.
Как отвечать
В C# есть финализатор, объявляется он тильдой перед именем класса. Компилятор превращает его в переопределение метода Finalize базового типа; написать такое переопределение руками или вызвать метод напрямую язык запрещает. Запустить финализацию извне нельзя, косвенно можно лишь дождаться очереди вызовом GC.WaitForPendingFinalizers или, наоборот, снять объект с очереди через GC.SuppressFinalize.
Дальше механика. Объект с финализатором сборщик не освобождает на первом проходе: он ставит его в очередь, отдельный поток выполняет тело, и память возвращается только следующим проходом. Отсюда правило: финализатор продлевает жизнь объекту и всему, на что тот ссылается, поэтому без нужды его не добавляют.
public void Dispose()
{
Release();
GC.SuppressFinalize(this);
}
~Handle() => Release();Правильная схема: публичный Dispose освобождает ресурс сразу и подавляет финализатор, а сам финализатор остаётся страховкой на случай, когда Dispose позвать забыли. Ещё лучше не писать его вовсе, а завернуть неуправляемый дескриптор в наследника SafeHandle, где финализация уже реализована.
Где спотыкаются
Говорят, что финализатор гарантированно отработает. Не гарантированы ни момент, ни сам факт вызова: при завершении процесса очередь может остаться неразобранной, поэтому сбрасывать буферы и дописывать файл оттуда нельзя.
Освобождают в финализаторе управляемые объекты. Порядок финализации не определён, и поле вашего объекта к этому моменту может быть уже собрано; финализатор трогает только неуправляемое, а с управляемым работает Dispose.
Ставят финализатор каждому классу с Dispose. Если своего неуправляемого дескриптора нет, он лишний: добавляет работу сборщику и задерживает освобождение памяти без всякой пользы.