C# 滥用IDisposable可从中受益吗;使用;被认为有害的言论?
接口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
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)的内容压缩为(可以说)更可读的内容。