Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 滥用IDisposable可从中受益吗;使用;被认为有害的言论?_C#_.net_Idisposable - Fatal编程技术网

C# 滥用IDisposable可从中受益吗;使用;被认为有害的言论?

C# 滥用IDisposable可从中受益吗;使用;被认为有害的言论?,c#,.net,idisposable,C#,.net,Idisposable,接口IDisposable的目的是有序地释放非托管资源。它与using关键字一起使用,该关键字定义了一个作用域,在该作用域结束后,相关资源将被处置 由于这种方法非常简洁,我反复尝试让类实现IDisposable,以便能够以不适合的方式滥用这种机制。例如,可以实现类来处理嵌套上下文,如下所示: class Context : IDisposable { // Put a new context onto the stack public static void PushContex

接口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
调用代码时的用法可能如下所示:

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
使用(Context.PushContext())
{
DoContextualStuff(Context.CurrentContext);

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

using(Html.BeginForm())
{
    //some form elements
}
虐待?微软(间接地)说不

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

“这样使用IDisposable接口是不是滥用了它”?可能吧

使用
作为纯粹的“作用域”构造是否有助于更明显的意图和更好的代码可读性?当然可以


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

你肯定不会是第一个以这种方式“滥用”IDisposable的人。可能我最喜欢在计时器中使用它,如下所示:

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

事实上,我很确定微软自己也在一些图书馆里使用它。我的经验法则是——如果它能提高可读性,那就去做吧。

还有很多其他的概念可能会被误用,以上就是其中之一,唯一的问题是可读性,记住你的代码应该是清晰的/可读的,并且可以被其他开发人员维护。我同意Habib的观点。永远想想那个可怜的混蛋,他必须在18个月后使用你的代码。这个混蛋很有可能就是你:-)这是一个主观的问题,但你可以注意到ASP.NET MVC框架以这种方式滥用IDisposable-例如
FormExtensions.BeginForm
可能重复我编辑过的问题让我更清楚我不是在寻求意见(我已经有了一个:“这很好用!”),但由于具体原因,此用法可能/将导致问题。与交易范围类似。与spender达成一致。微软使用它的方式并不总是释放资源,所以我认为它是“允许的”。也就是说,可读性应该是你关心的问题。我认为
BeginForm
是清晰的;从列表中弹出,不是很多。如果
using
行包含“Push”,我会说弹出非常明显。为什么不直接使用
try/finally
?它同样可读。@ChrisDunaway
使用
已经是
try/finally
的语法甜点,但是有一个方便的标准界面。如果没有
IDisposable
,调用方需要知道如何清理,而
使用
会给创建者带来负担。为什么不直接使用
try/finally
?它同样可读。@ChrisDunaway在这种情况下,我不同意,主要是因为(a)在这种情况下,您最终会得到一个空的
finally
,以及(b)IMO,因为
使用
try/finally
更清楚地声明范围内的意图。对我来说,
使用
表示“我正在用这个对象做一些事情,希望它在之后消失”
try/finally
说“我可能在这里遇到一个异常,我想处理它”。我不得不不同意你的部分陈述
try/finally
(没有catch子句)并不意味着任何异常。finally会有任何必要的清理代码,并说“我想做下面的事情,然后最终清理”。至少我是这样读的。为什么不直接使用
try/finally
?它同样可读。@ChrisDunaway这里的要点是在using块中计时操作,而不是防止异常。您可以使用myTimer、do…
将其读取为
,并通过这样做,将原本是三行代码(timer.Start、timer.Stop、timer.SendToServer)的内容压缩为(可以说)更可读的内容。