在C++中,我习惯于使用哨兵模式来确保在块或函数退出时正确释放所获取的资源(例如,参见here)。例如,我用它来获取图形状态,然后我可以对状态进行任何操作,并且当哨兵对象(引用)超出范围时,它将被放回原处。

现在,我正在使用C#,并且相同的技巧也无效,因为析构函数要等到稍后的who-knows-when才会被调用。

释放对象的最后一个引用时,是否有其他方法可以保证触发?还是我只需要记住从某些本应使用哨兵的方法返回之前调用一些Restore()或Apply()或DoYourThing()方法?

最佳答案

在这种情况下,C#提供了using块,该块可用于实现IDisposable的任何对象。

例如,如果您具有class Foo : IDisposable类型,则可以执行以下操作:

using (new Foo(/* ... */)) {
    // Your code that depends on this resource.
}

这等效于:
Foo x = new Foo(/* ... */);
try {
    // Your code
} finally {
    if (x != null) {
        ((IDisposable)x).Dispose();
    }
}

当然,除了您无权访问x。但是,如果需要,可以通过在using块中创建一个变量来获得这种访问权限:
using (Foo foo = new Foo(/* ... */)) {
    // Your code that uses "foo"
}

创建可以通过这种方式或由垃圾收集器处理的类的标准方法是:
class Foo : IDisposable {
    protected virtual void Dispose(bool disposing) {
        // Your cleanup code goes here.
    }

    public void Dispose() {
        GC.SuppressFinalize(this);
        Dispose(true);
    }

    ~Foo() {
        Dispose(false);
    }
}

10-04 14:22