C# 我是否需要使用;使用;每个实现IDisposable的对象中的关键字?
我打电话给一个第三方库,在那里有很多类实现了IDisposableC# 我是否需要使用;使用;每个实现IDisposable的对象中的关键字?,c#,.net,idisposable,using-statement,C#,.net,Idisposable,Using Statement,我打电话给一个第三方库,在那里有很多类实现了IDisposable 我是否需要在所有这些应用程序上都使用using模式?您不需要这样做,但这是一种很好的做法 它确保无论是否发生异常,都能正确清理资源 IDisposable只应在需要清理资源的类上实现,因此确保它们确实可以实现是一种良好的做法 可能需要直接调用Dispose而不是using块(WCF代理为此而臭名昭著),但这不是一般情况 简而言之,没有人会强迫你使用它们,但你真的应该这样做。你不“需要”这样做,但你很可能应该这样做 如果不这样做,
我是否需要在所有这些应用程序上都使用using模式?您不需要这样做,但这是一种很好的做法 它确保无论是否发生异常,都能正确清理资源
IDisposable
只应在需要清理资源的类上实现,因此确保它们确实可以实现是一种良好的做法
可能需要直接调用Dispose
而不是using块(WCF代理为此而臭名昭著),但这不是一般情况
简而言之,没有人会强迫你使用它们,但你真的应该这样做。你不“需要”这样做,但你很可能应该这样做 如果不这样做,可能会耗尽一些资源,甚至可能得到不正确的结果,这取决于库的具体功能
但是,如果不知道
Dispose()
在这些对象上到底做了什么,您应该明确地调用它,以避免意外问题。(您不必直接这样做,您可以使用using
,正如您所建议的那样。)当类实现IDisposable时,它表示它宁愿由您的代码处理,也不愿等待垃圾收集器稍后处理它。所以,是的,如果一个类实现了IDisposable,您应该在它超出范围之前调用Dispose(或use using)
是否应该使用using而不是直接调用Dispose?再一次,是的。要确保对象已被释放,您必须确保即使引发异常也已释放对象,方法是将代码封装在try{…}finally{}块中,该块将在finally块中释放对象。这会导致不必要的混乱,您很容易忘记添加finally块
用于此作业更安全。这在很大程度上取决于相关变量的范围 本地范围:使用 如果变量的作用域是局部的,则应使用块将相关代码括在
中。请记住,using
块只是下面的语法糖,假设using
包含一个名为obj
的IDisposable对象:
var obj = // ...
try
{
// ...
}
finally
{
obj.Dispose();
}
这意味着即使抛出异常,您的对象也将被释放
类范围:IDisposable
如果对象的作用域为类级别,则不应使用
块将其封闭在中。相反,您的类应该通过实现IDisposable
,将Dispose
方法公开给使用它的任何代码,并在那里处置对象
从不使用:完成
通常,通过依赖类的终结器来处理其对象,在依赖链的任何一点将处理责任转移给垃圾收集器是一种不好的做法。这削弱了Dispose
和Finalize
之间的差异:Dispose
用于明确、即时的资源释放,而Finalize
则更被动。依靠Finalize
调用Dispose
,会破坏这种目的分离。然而,这更多的是我的编程风格问题,代表了一种观点——不要把它当作事实。在接受我的建议之前,你应该自己对此进行更多的研究——当然,你也应该阅读一些不可避免的评论。我肯定我至少错过了重要的例外情况。@奇怪的是,我不太确定“没有人被迫[…]”使用语句。我想说的是,如果某个代码块利用了某个类,并且实现了IDisposable
@MatíasFidemraizer,则必须使用它-我只是说,没有使用警察强制使用在IDisposable
上使用。也许我错了,西班牙有一个;)@MatíasFidemraizer-顺便说一句,它是Oded
,而不是Odded
@Odded绝对是西班牙的!!;)没有警察强迫这么做,但为什么要冒险?如果有好的语法糖,为什么要尝试/抓住/最后呢笨蛋,对不起,奥德,我做了两次。抱歉。您提到了许多其他人似乎没有提到的东西:您有时希望显式调用Dispose(),而不是使用using块。在您说“Finalize,哦,那是Java,不是C#”之前,.NET中的析构函数通常被称为Finalize
@AndrewBarber Yes,这就是为什么我继续发布我的答案,即使有那么多人已经发布了。有时——很多次——显式调用Dispose
更好使用
对于类作用域变量没有任何意义。@Zenexer:它不仅仅是“经常被名称Finalize
引用”。如果类重写了Object.Finalize()
,则在调用该方法或使用GC.SuppressFinalize()
指示不需要该方法之前,不会对该对象进行垃圾收集。由于几乎所有正确使用C#析构函数的程序(析构函数是请求编译器重写Object.Finalize
)都必须包含调用GC.SuppressFinalize()
,因此术语“Finalize”似乎比“析构函数”更贴切,虽然后一个术语仍然是描述C#wrapper的必要术语。@supercat我知道有很多理由认为Finalize
最合适(这就是我使用它的原因),但是你会惊讶于有多少人听到它时会尖叫“Java!”。不过,这是一个很好的解释。在对象超出范围之前,应该对您“拥有”的对象(您使用new
或工厂方法创建)调用Dispose。使用块是实现这一点的简单方法。这是理想的模式。如果您这样做,您将确保所有底层资源