当只有_unmanaged_个资源在起作用时,能否简化C#一次性模式?

时间:2019-07-07 17:18:31

标签: c# garbage-collection finalizer suppressfinalize

(注意:该问题与Calling GC.SuppressFinalize() from within a finalizer相关,但不是重复项,因为此问题明确地专门针对无托管资源的情况,而这明确是关于同时拥有托管资源和非托管资源的。)

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),其功能与上面相同。在这种情况下,它可能最终被终结器本身(间接)调用,但是据我所知,这样做没有害处。

这种形式的“一次性模式”似乎更简单,据我所知,完全可以满足需要-在不涉及托管资源的情况下。但是,我在任何地方都没有看到它,或者至少在任何地方都没有看到它宽容

这种模式有意义吗,还是从根本上来说是有缺陷的?

0 个答案:

没有答案