我有一个方法,里面有一个try/catch/finaly
块。在try块中,我声明SqlDataReader
如下:
SqlDataReader aReader = null;
aReader = aCommand.ExecuteReader();
在finally
块中,手动处理的对象是在类级别设置的对象。因此,实现IDisposable
的方法中的对象(例如上面的SqlDataReader
)是否会被自动处理?执行while循环后,Close()
会调用aReader
以获取阅读器的内容(调用Dispose()
时应为Close()
)。如果没有调用Close()
,当方法完成或对象超出范围时,是否会自动关闭/处置此对象?
编辑:我知道using
声明,但有些情况令我感到困惑。
答案 0 :(得分:25)
不,当对象超出范围时,对象不会自动处理。
如果/当他们被垃圾收集时,他们甚至不能保证被处置,尽管许多IDisposable
对象实施了“后备”终结器以帮助确保他们最终被处置。
您有责任确保处置任何IDisposable
个对象,最好将它们包裹在using
块中。
答案 1 :(得分:8)
您应该使用using {...}
块来包装您的IDisposable对象 - 当使用块结束时,将调用Dispose()
方法(对于SqlDataReader传递给Close()
方法) 。如果你不使用using
,那么当对象超出范围时,不会被自动处理 - 它将取决于对象终结器,如果它有一个,可以去除垃圾收集时的资源
using (SqlDataReader aReader = aCommand.ExecuteReader())
{
// ... do stuff
} // aReader.Dispose() called here
答案 2 :(得分:1)
Dispose模式不保证哪些对象将调用Dispose来处理其他对象;它有时会发生,但你不应该在乎。相反,您有责任确保为所有IDisposable对象调用Dispose()。最好的方法是使用using
语句。例如:
using (SqlDataReader aReader = aCommand.ExecuteReader())
{
// your code
}
答案 3 :(得分:1)
我同意以上所有内容。您应确保自己致电Dispose()
,最简单的方法是使用using
语句(您也可以在finally
块中自行完成此操作 - 这更详细,但有时是必要的)。如果你不这样做,你会发现你的应用程序泄漏了非托管资源,如句柄,甚至非托管内存,特别是如果正在使用所有这些COM组件下面的某个地方,或者正在调用Win32 API。这显然会导致性能和稳定性问题,以及过多的资源使用。
仅仅因为实现IDisposable
的对象“应该”实现调用其Dispose(bool disposing)
方法来释放非托管资源的终结器,并不能保证会发生这种情况,所以你绝对不应该依赖它。例如,有关此点的更多信息,请参阅http://msdn.microsoft.com/en-us/library/b1yfkh5e%28VS.71%29.aspx。
另外,要记住的是,如果您的类型具有一次性成员,则您的类型应该实现IDisposable
(除非这些成员的生命周期由另一种类型管理,显然可能会获得(如果你只在一种方法中使用这些成员,或者实现一个特定的功能),你应该考虑在使用它们的方法中将它们作为局部变量/参数。
答案 4 :(得分:0)
我对这句话感到困惑“在finally块中,手动处理的对象是那些在类级别设置的对象。”通过在类级别设置的对象,您的意思是字段吗?您可能不应该在普通方法中处理这些,因为那时字段的生命周期是不可预测的,并且取决于您碰巧调用的方法。最好在Dispose方法中实现IDisposable和处理字段。
答案 5 :(得分:-2)
Using语句有帮助吗?