c# - 如何在 C# 中执行哨兵模式?

标签 c# c++ design-patterns

在 C++ 中,我习惯于使用哨兵模式来确保在 block 或函数退出时正确释放获取的资源(例如,参见 here)。例如,我用它来获取图形状态,然后我可以对该状态做任何我想做的事情,当哨兵对象(引用)超出范围时它会被放回。

现在我正在使用 C#,但同样的技巧不起作用,因为析构函数直到后来谁知道什么时候才会被调用。

是否有其他方法保证在释放对象的最后一个引用时触发?或者我是否只需要记住在从任何我会使用哨兵的方法返回之前调用一些 Restore() 或 Apply() 或 DoYourThing() 方法?

最佳答案

C# 与 C++ 一样,在销毁对象时调用终结器。它们与C++的形式相同,即:

~ClassName()
{
}

不过如您所知,C# 没有确定性的内存管理,因此这并不是一个很好的保证。作为直接结果,您应该在 C# 中使用终结器来释放非托管资源。相反,我们使用 IDisposable 接口(interface)。这在实现程序上公开了一个方法,Dispose,旨在在您想要释放非托管资源时调用。

public class MyDisposable : IDisposable
{
    public void Dispose()
    {
        // get rid of some expensive unmanaged resource like a connection
    }
}

我们还可以使用 using 糖来允许在 using block 终止时(优雅地或不优雅地)语义调用 Dispose()

using(var disposable = new MyDisposable)
{
    // Do something with the disposable
} // Dispose is invoked here

如果您发现自己正在使用终结器 Dispose,您可以考虑使用GC.SuppressFinalize 方法,尽管这有点超出我的范围范围。关于这个 here 在 StackOverflow 的其他地方有一个非常好的讨论

这当然可以用来执行类似 RAII 的诡计,例如

using(var guard = new Guard(resource))
{

}

关于c# - 如何在 C# 中执行哨兵模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26020490/

相关文章:

c# - Rhino Mocks 约束和字典参数

c++ - 指针/引用 *& 运算符重载

c++ - 即使在 C++20 中 std::memcpy 也不是 constexpr 的原因是什么?

c - 可能会失败的分配和操作顺序的正确模式

c# - 支持处理 ADO.NET 数据提供程序独立代码中特定于数据提供程序的差异?

c# - 如何在 ASP.NET C# 中的新选项卡(而不是窗口)中打开页面?

C# 浮点文字 : Why compiler does not DEFAULTS to the left hand side variable type

c++ - "Implicit instantiation of undefined template"前向声明模板类时

c++ - 对象依赖性以及其中之一不再存在时的处理情况

java - 了解构建器/工厂模式