14

我有一个方法,里面有一个try/catch/finaly块。在 try 块中,我声明SqlDataReader如下:

SqlDataReader aReader = null;          
aReader = aCommand.ExecuteReader();

在该finally块中,手动处理的对象是在类级别设置的对象。那么实现的方法中的对象IDisposable,例如SqlDataReader上面的,它们会被自动处理吗?Close()aReader执行 while 循环以获取阅读器的内容后调用(应该是Dispose()调用的内容Close())。如果没有调用Close(),当方法完成或对象超出范围时,该对象是否会自动关闭/处置?

编辑:我知道该using声明,但有些情况让我感到困惑。

4

6 回答 6

27

不,对象超出范围时不会自动处置。

如果/当它们被垃圾收集时,它们甚至不能保证被释放,尽管许多IDisposable对象实现了“后备”终结器以帮助确保它们最终被释放。

您有责任确保任何IDisposable对象都已被处置,最好将它们包装在一个using块中。

于 2009-12-02T13:46:21.637 回答
8

您应该使用一个using {...}块来包装您的 IDisposable 对象 - 该Dispose()方法(对于 SqlDataReader 传递给该Close()方法)将在 using 块结束时被调用。如果你不使用using,对象在超出范围时不会被自动释放 - 它将由对象终结器(如果有的话)在垃圾收集时摆脱资源

using (SqlDataReader aReader = aCommand.ExecuteReader())
{
    // ... do stuff
}   // aReader.Dispose() called here
于 2009-12-02T13:43:16.697 回答
2

我同意以上所有观点。您应该确保自己调用Dispose(),最简单的方法是使用using语句(您也可以在finally块中自己执行此操作 - 这更冗长,但有时是必要的)。如果你不这样做,你会发现你的应用程序泄漏了非托管资源,例如句柄,甚至是非托管内存,尤其是在所有这些之下的某个地方正在使用一些 COM 组件,或者正在对 Win32 API 进行调用。这显然会导致性能和稳定性问题,以及过多的资源使用。

仅仅因为实现IDisposable“应该”的对象实现了一个调用它们的Dispose(bool disposing)方法来释放非托管资源的终结器,并不能保证这会发生,所以你绝对不应该依赖它。有关这一点的更多信息,请参见例如http://msdn.microsoft.com/en-us/library/b1yfkh5e%28VS.71%29.aspx

另外,要记住的另一件事是,如果您的类型具有一次性成员,则您的类型应该实现IDisposable(除非这些成员的生命周期由另一种类型管理,这显然可能会变得混乱),或者,如果您只在一种方法中使用这些成员,或者为了实现一个特定的功能,您应该考虑在使用它们的方法中使它们成为局部变量/参数。

于 2009-12-02T13:57:38.720 回答
1

Dispose 模式不保证哪些对象将对哪些其他对象调用 Dispose。它有时可能会发生,但你不应该在意。相反,您有责任确保为所有 IDisposable 对象调用 Dispose()。最好的方法是使用using声明。例如:

using (SqlDataReader aReader = aCommand.ExecuteReader())
{
    // your code
}
于 2009-12-02T13:44:22.593 回答
0

我对“在finally块中,手动处理的对象是在类级别设置的对象”的说法感到困惑。通过在类级别设置的对象,您是指字段吗?您可能不应该在普通方法中处理这些,因为字段的生命周期是不可预测的,并且取决于您碰巧调用了哪些方法。最好在 Dispose 方法中实现 IDisposable 和 dispose 字段。

于 2009-12-02T13:51:22.740 回答
-2

Using语句可能有帮助吗?

于 2009-12-02T13:44:20.193 回答