滥用 IDisposable 以从 "using" 语句中获益是否被认为是有害的?

Is abusing IDisposable to benefit from "using" statements considered harmful?

接口IDisposable的目的是以有序的方式释放非托管资源。它与 using 关键字密切相关,该关键字定义了一个范围,在该范围结束后将处理相关资源。

因为这个机制非常巧妙,我一再想要 类 实现 IDisposable 以便能够以不适合的方式滥用这个机制。例如,可以实现 类 来处理这样的嵌套上下文:

class Context : IDisposable
{
    // Put a new context onto the stack
    public static void PushContext() { ... }

    // Remove the topmost context from the stack
    private static void PopContext() { ... }

    // Retrieve the topmost context
    public static Context CurrentContext { get { ... } }

    // Disposing of a context pops it from the stack
    public void Dispose()
    {
        PopContext();
    }
}

调用代码的用法可能如下所示:

using (Context.PushContext())
{
   DoContextualStuff(Context.CurrentContext);
} // <-- the context is popped upon leaving the block

(请注意,这只是一个示例,与本题无关。)

在离开 using 语句的范围时调用 Dispose() 这一事实也可以被用来实现各种依赖于范围的事情,例如定时器。这也可以通过使用 try ... finally 构造来处理,但在那种情况下,程序员将不得不手动调用某些方法(例如 Context.Pop),而 using 构造可以为 thon 执行此操作。

IDisposable 的这种用法与其预期目的不符 as stated in the documentation,但诱惑依然存在。

是否有具体的理由来说明这是一个坏主意并永远打消我的幻想,例如垃圾收集的复杂性、异常处理等。或者我应该继续滥用这个语言概念来放纵自己方式?

因此在 asp.net MVC 视图中,我们看到以下结构:

using(Html.BeginForm())
{
    //some form elements
}

虐待?微软说不(间接)。

如果您有一个构造,需要在完成后发生一些事情,IDisposable通常可以锻炼得很好。我已经不止一次这样做了。

"Is it an abuse of the IDisposable interface to use it this way"?应该是吧。

using 用作纯粹的 "scoping" 构造是否会使意图更明显,代码的可读性更好?当然可以。

后者对我来说胜过前者,所以我说用它。

您肯定不会是第一个以这种方式 'abuse' IDisposable 的人。可能我最喜欢用在定时器中,如 StatsD.NET client 所示:

using StatsdClient;
...
using (statsd.LogTiming( "site.db.fetchReport" ))
{
  // do some work
}
// At this point your latency has been sent to the server

事实上,我很确定 Microsoft 自己在某些库中使用它。我的经验法则是 - 如果它提高了可读性,那就去做吧。