Удаляет ли финализатор объект в C#
Что проверяют
Отделяете ли вы освобождение неуправляемых ресурсов от освобождения памяти. Финализатор ничего не удаляет, память возвращает сборщик мусора, и кандидат, который это путает, обычно так же путает Dispose с деструктором из C++.
Как отвечать
Нет, не удаляет. Финализатор это метод, который среда вызывает перед тем, как память объекта будет возвращена, и нужен он для неуправляемых ресурсов: дескрипторов файлов, сокетов, памяти, выделенной вне управляемой кучи.
Важно, что финализатор не ускоряет освобождение, а замедляет его. Объект с финализатором при создании попадает в особый список. Когда сборщик находит его недостижимым, память он не забирает: объект переводится в очередь на финализацию, оживает до следующей сборки и переезжает в старшее поколение. Сам финализатор выполняется отдельным потоком, и только следующая сборка освобождает память. То есть один лишний финализатор стоит объекту целого поколения жизни.
Отсюда правило: ресурсы освобождают детерминированно, через IDisposable и using. Финализатор оставляют как страховку на случай, если Dispose не вызвали, а в самом Dispose зовут GC.SuppressFinalize(this), чтобы снять объект с очереди. В современном коде обёртки вроде SafeHandle закрывают эту задачу, и писать свой финализатор почти никогда не нужно.
Где спотыкаются
Считают финализатор аналогом деструктора C++ и ждут вызова при выходе из области видимости. Момент вызова недетерминирован, порядок между объектами не определён, а при завершении процесса финализаторы могут не выполниться вообще.
Вторая ошибка: обращаются в финализаторе к другим управляемым объектам. К этому моменту они могут быть уже финализированы, а необработанное исключение в потоке финализации роняет процесс целиком. Внутри трогают только неуправляемое.
Третья: пишут Dispose, но забывают GC.SuppressFinalize. Ресурс освобождён вовремя, а объект всё равно проходит через очередь финализации и живёт лишнюю сборку, то есть плата за финализатор остаётся там, где она уже не нужна.