Можно ли упростить шаблон одноразового использования C #, если в игре находятся только _unmanaged_ ресурсы? - PullRequest
0 голосов
/ 07 июля 2019

(Примечание: этот вопрос относится к вызову 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), который имеет ту же функцию, что и выше. В этом случае он может быть вызван (косвенно) из самого финализатора, но, насколько я знаю, в этом нет никакого вреда.

Эта форма одноразового шаблона кажется более простой и, насколько я могу судить, вполне адекватной - , когда не задействованы управляемые ресурсы . И все же я нигде этого не видел, или, по крайней мере, я не видел его , потворствовал .

Имеет ли смысл эта схема или она в корне ошибочна?

...