【问题标题】:Implementing RAII in C#在 C# 中实现 RAII
【发布时间】:2012-04-02 08:00:32
【问题描述】:

我有一个 InfoPath 表单,我需要有条件地禁用它的 OnChange 事件。由于在表单加载后无法绑定事件处理程序,我不得不依赖一个全局计数器来指示是否应该执行 OnChange 事件。 在每个 OnChange 事件中,我在执行任何操作之前检查是否 SuppressEventsCount == 0。 为了在某​​个函数或另一个函数的执行过程中抑制事件,我只需设置 SuppressEventsCount++,并在函数退出时再次设置 -- 。这样做的最大问题是它不是异常安全的。所以我有一个好主意,将 SuppressEvents 计数器包装在一个实现 iDisposable 的类中

using(SuppressEvents s = new SuppressEvents()){
   // OnChange events fired here are ignored
} // OnChange events enabled again

这是可行的,但它仍然不如完全不需要使用“using”指令的 c++ 解决方案理想。

有没有办法:

  1. 在对象超出范围时触发析构函数或某些函数,或者
  2. 完全防止在“使用”指令之外初始化 SuppressEvents 对象

【问题讨论】:

  • 查看这个问题:stackoverflow.com/q/2101524/6345(使用 IDisposable 和“使用”作为获取“范围行为”以实现异常安全的手段是否滥用?)

标签: c# raii


【解决方案1】:

没有,也没有。 using 是最接近 RAII 的(更准确地说,我们谈论的是 RAII 惯用语对象被破坏后的资源释放)。

更直接地回答你的观点:

  1. IDisposable(以及扩展名 using)的创建正是因为在 .NET 中无法做到这一点。
  2. using 是编译为 try/finally 的语法糖,并且只要求对象是 IDisposable,因此您无法区分 using 语句内部和外部的用法。

【讨论】:

    【解决方案2】:

    关于问题 2,可以通过为代码的使用者提供不同的接口来绕过它。与其提供实现IDisposable 的公共类,并希望他们将其包装在using 中,不如提供一个静态方法,该方法采用一个函数在“抑制”上下文中执行:

    public static class EventSuppressor {
        public void Suppress(Action action) {
            using (var s = new SuppressActions()) {
                action();
            }
        }
    
        private class SuppressActions : IDisposable {
            ...
        }
    }
    

    那么消费者可以这样使用:

    EventSuppressor.Suppress(() => {
        // OnChange events fired here are ignored
    }) // OnChange events enabled again
    

    当然,你必须弄清楚这种设计是否合适,因为这会导致额外的函数调用、编译器生成的类和闭包等。

    【讨论】:

      【解决方案3】:

      回答你的两个问题:

      1. 不,没有,.NET 中的垃圾收集本质上不是确定性的

      【讨论】:

        【解决方案4】:

        如果您可以从 C# 迁移到 C++.NET(如果使用 clr:safe 编译仍然是 100% .NET),那么您可以使用 msclr::auto_handle,它的作用就像智能指针,例如 auto_ptr 等...

        它在 IL 的幕后真正做的是一堆 try/fault 命令,但这对开发人员和用户来说是完全不可见的。整个过程只是更好的IMO。

        【讨论】:

          猜你喜欢
          • 2010-09-26
          • 2011-12-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多