(Примечание: этот вопрос относится к вызову GC.SuppressFinalize () из финализатора , но является не дубликатом, поскольку этот вопрос явно относится именно к случаю нет управляемых ресурсов , тогда как этот явно относится к наличию как управляемых, так и неуправляемых ресурсов .)
Классический Одноразовый шаблон в C # выглядит примерно так:
public class MyClass : IDisposable {
bool alreadyDisposed = false;
void Dispose(bool calledFromDisposeMethod) {
if (!alreadyDisposed) {
alreadyDisposed = true;
if (calledFromDisposeMethod) {
GC.SuppressFinalize(this);
// Release _managed_ resources here
}
// Release _unmanaged_ resources here
}
}
public void Dispose() => Dispose(true);
~MyClass() => Dispose(false);
}
Обоснование состоит в том, что когда экземпляр MyClass
удаляется явно (путем вызова метода Dispose()
- возможно, но не обязательно, с использованием using
), тогда мы хотим высвободить все ресурсы, управляемые и неуправляемые аналогично, тогда как, когда экземпляр собирается для сбора мусора, не утилизировав его, мы хотим только высвободить неуправляемые ресурсы, оставляя управляемые ресурсы в другом месте (например, позволяя им оставаться до тех пор, пока они сами не будут удалены). сборка мусор). * * тысяча двадцать одна
Кстати, обратите внимание на вызов GC.SuppressFinalize(this)
, который сообщает сборщику мусора, что нет необходимости вызывать финализатор, если и когда экземпляр получает сборщик мусора, так как Dispose()
уже был вызван и позаботился об освобождении ресурсов. , Из-за использования флага alreadyDisposed
нет реальной опасности, если финализатор действительно вызывается, но это не нужно, и необходимо сообщить сборщику мусора, что позволяет ему пропустить помещение экземпляра в очередь финализации, что потенциально может его освободить (и другие вещи, на которые он ссылается) быстрее.
Но что насчет случая, когда у есть только неуправляемые ресурсы ? Я ожидаю найти следующую, несколько более простую модель:
public class MyClass : IDisposable {
bool alreadyDisposed = false;
void Dispose() {
if (!alreadyDisposed) {
alreadyDisposed = true;
// Release (unmanaged) resources here
GC.SuppressFinalize(this);
}
}
~MyClass() => Dispose();
}
Обратите внимание еще раз на вызов GC.SuppressFinalize(this)
, который имеет ту же функцию, что и выше. В этом случае он может быть вызван (косвенно) из самого финализатора, но, насколько я знаю, в этом нет никакого вреда.
Эта форма одноразового шаблона кажется более простой и, насколько я могу судить, вполне адекватной - , когда не задействованы управляемые ресурсы . И все же я нигде этого не видел, или, по крайней мере, я не видел его , потворствовал .
Имеет ли смысл эта схема или она в корне ошибочна?