26

我想知道什么时候应该和不应该将东西包装在 USING 块中。

据我了解,编译器将其转换为 try/finally,finally 在对象上调用 Dispose()。

我总是在数据库连接和文件访问周围使用 USING,但它更多的是出于习惯而不是 100% 的理解。我知道您应该明确(或使用)控制资源的 Dispose() 对象,以确保立即释放它们,而不是在 CLR 感觉时释放它们,但这就是我的理解崩溃的地方。

IDisposables 超出范围时是否不会被处置?

当我的对象使用 Dispose 来整理自己时,我是否只需要使用 USING ?

谢谢

编辑:我知道关于 USING 关键字还有其他几篇文章,但我对与 CLR 相关的答案以及内部发生的确切情况更感兴趣

安德鲁

4

3 回答 3

22

不,IDisposable项目超出范围时不会被处置。正是出于这个原因,我们需要IDisposable- 进行确定性清理。

他们最终会被垃圾收集,如果有一个终结器,它将(可能)被调用 - 但这可能是未来很长一段时间(对连接池等不利)。垃圾收集依赖于内存压力——如果没有什么需要额外的内存,则不需要运行 GC 循环。

有趣的是(也许)在某些情况下“使用”是一种痛苦——当违规类有时会抛出异常时Dispose()。WCF 是一个罪犯。我在这里讨论了这个话题(有一个简单的解决方法) 。

基本上 - 如果类实现了IDisposable,并且您拥有一个实例(即您创建了它或其他),那么您的工作就是确保它被处理掉。这可能意味着通过“使用”,或者可能意味着将其传递给另一段承担责任的代码。

我实际上已经看到了以下类型的调试代码:

#if DEBUG
    ~Foo() {
        // complain loudly that smoebody forgot to dispose...
    }
#endif

Dispose打电话的地方GC.SuppressFinalize

于 2008-11-25T12:37:30.617 回答
5

“当 IDisposables 超出范围时,它们是否不会被丢弃?”

不。如果 IDisposable 对象是finalizable,这不是一回事,那么它会在垃圾回收时被终结。

这可能很快,也可能几乎永远不会。

Jeff Richter 的 C#/CLR 书在所有这些方面都非常出色,Framework Design Guidelines 书也很有用。

当我的对象使用 Dispose 来整理自己时,我是否只需要使用 USING ?

当对象实现 IDisposable 时,您只能使用“使用”。如果您尝试不这样做,编译器将反对。

于 2008-11-25T12:38:43.703 回答
2

要添加到其他答案,您应该using在对象拥有托管内存以外的任何资源时使用(或显式 Dispose)。例如文件、套接字、数据库连接,甚至 GDI 绘图句柄。

垃圾收集器最终会最终确定这些对象,但只是在未来某个未指定的时间。您不能依赖它及时发生,同时您可能已经用完了该资源。

于 2008-11-25T12:55:01.580 回答