C# 当对象超出范围/方法完成时调用Dispose()vs

C# 当对象超出范围/方法完成时调用Dispose()vs,c#,idisposable,using,using-statement,C#,Idisposable,Using,Using Statement,我有一个方法,里面有一个try/catch/finaly块。在try块中,我声明SqlDataReader,如下所示: SqlDataReader aReader = null; aReader = aCommand.ExecuteReader(); 在finally块中,手动处理的对象是在类级别设置的对象。那么,在方法中实现IDisposable的对象,比如上面的SqlDataReader,它们会被自动处理吗关闭()在执行while循环以获取读卡器的内容(调用关闭()时应

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

SqlDataReader aReader = null;          
aReader = aCommand.ExecuteReader();
finally
块中,手动处理的对象是在类级别设置的对象。那么,在方法中实现
IDisposable
的对象,比如上面的
SqlDataReader
,它们会被自动处理吗<代码>关闭()在执行while循环以获取读卡器的内容(调用
关闭()
时应为
Dispose()
)后,在
区域der上调用。如果没有调用
Close()
,当方法完成或对象超出范围时,是否会自动关闭/处置此对象


编辑:我知道
using
语句,但有些场景让我感到困惑。

您应该使用
using{…}
块将IDisposable对象包装在中-using块结束时将调用
Dispose()
方法(对于SqlDataReader,该方法传递到
Close()
方法)。如果不使用
使用,则对象超出范围时将不会自动处理-垃圾收集时,将由对象终结器(如果有)来清除资源

using (SqlDataReader aReader = aCommand.ExecuteReader())
{
    // ... do stuff
}   // aReader.Dispose() called here

该语句是否有帮助?

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

using (SqlDataReader aReader = aCommand.ExecuteReader())
{
    // your code
}

不,对象超出范围时不会自动释放

它们甚至不能保证在被垃圾收集时被释放,尽管许多
IDisposable
对象实现了一个“回退”终结者来帮助确保它们最终被释放


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

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

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

仅仅因为实现
IDisposable
“应该”实现调用其
Dispose(bool disposing)
方法释放非托管资源的finalizer,并不保证会发生这种情况,所以您绝对不应该依赖它。例如,有关这一点的更多信息,请参见

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