调用 Dispose() 与对象超出范围/方法完成时的比较
我有一个方法,里面有一个 try/catch/finaly 块。在 try 块中,我声明 SqlDataReader
如下:
SqlDataReader aReader = null;
aReader = aCommand.ExecuteReader();
在 finally
块中,手动释放的对象是在类级别设置的对象。那么实现IDisposable
的方法中的对象,例如上面的SqlDataReader
,它们会被自动释放吗?执行 while 循环后,在 aReader
上调用 Close()
以获取读取器的内容(应该是 Dispose()
,因为调用关闭()
)。如果没有调用 Close()
,当方法完成或对象超出范围时,该对象是否会自动关闭/处置?
编辑:我知道 using
语句,但有些场景让我感到困惑。
I have a method, which has a try/catch/finaly
block inside. Within the try block, I declare SqlDataReader
as follows:
SqlDataReader aReader = null;
aReader = aCommand.ExecuteReader();
In the finally
block, the objects which are manually disposed of are those which are set at the class level. So objects in the method which implement IDisposable
, such as SqlDataReader
above, do they get automatically disposed of? Close()
is called on aReader
after a while loop executes to get the contents of the reader (which should be Dispose()
as that calls Close()
). If there is no call to Close()
, would this object be closed/disposed of automatically when the method finishes or the object goes out of scope?
EDIT: I am aware of the using
statement but there are scenarios which are confusing me.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
不,对象超出范围时不会自动处置。
尽管许多 IDisposable 对象实现了“后备”终结器以帮助确保它们最终被处置,但如果/当它们被垃圾收集时,甚至不能保证它们会被处置。
您有责任确保所有
IDisposable
对象都已被处置,最好将它们包装在using
块。No, objects are not automatically disposed when they go out of scope.
They're not even guaranteed to be disposed if/when they're garbage-collected, although many
IDisposable
objects implement a "fallback" finaliser to help ensure that they're eventually disposed.You are resposible for ensuring that any
IDisposable
objects are disposed, preferably by wrapping them in ausing
block.您应该使用
using {...}
块将 IDisposable 对象包装在 -Dispose()
方法中(对于 SqlDataReader,该方法传递给Close( )
方法)将在 using 块结束时被调用。如果您不使用using
,则该对象在超出范围时将不会被自动处置 - 这将取决于对象终结器(如果有的话)当资源被垃圾收集时将其清除You should use a
using {...}
block to wrap your IDisposable objects in - theDispose()
method (which for SqlDataReader passes off to theClose()
method) will be called when the using block ends. If you do not useusing
, the object will not be automatically disposed when it goes out of scope - it will be up to the object finalizer, if it has one, to get rid of resources when it is garbage collected我同意以上所有内容。您应该确保自己调用
Dispose()
,最简单的方法是使用using
语句(您也可以在finally 中自己执行此操作)
块 - 这更详细,但有时是必要的)。如果您不这样做,您可能会发现您的应用程序泄漏了非托管资源,例如句柄,甚至是非托管内存,特别是在所有这些之下的某个地方正在使用某些 COM 组件,或者正在对 Win32 API 进行调用。这显然会导致性能和稳定性问题,以及资源使用过多。仅仅因为实现 IDisposable 的对象“应该”实现调用其 Dispose(bool dispose) 方法来释放非托管资源的终结器,并不能保证这种情况会发生,因此您绝对不应该依赖它。例如,请参阅 http://msdn.microsoft .com/en-us/library/b1yfkh5e%28VS.71%29.aspx 了解有关这一点的更多信息。
另外,需要记住的其他事情是,如果您的类型具有可处置的成员,那么您的类型应该实现 IDisposable(除非这些成员的生命周期由其他类型管理,这显然可能会导致混乱),或者,如果您只在一种方法中使用此类成员,或者为了实现一项特定的功能,您应该考虑在使用它们的方法中将它们设置为局部变量/参数。
I agree with all of the above. You should make sure you call
Dispose()
yourself, and the easiest way to to this is with theusing
statement (you can also do this yourself in thefinally
block - this is more verbose, but sometimes necessary). If you don't do this you can find your application leaking unmanaged resources such as handles, or even unmanaged memory, especially if somewhere underneath all of this some COM components are being used, or calls are being made into the Win32 API. This can obviously lead to performance and stability problems, as well as excessive resource usage.Just because objects that implement
IDisposable
"should" implement a finaliser that calls theirDispose(bool disposing)
method to free unmanaged resources, is no guarantee that this will happen, so you definitely should not rely on it. See, for example, http://msdn.microsoft.com/en-us/library/b1yfkh5e%28VS.71%29.aspx for more information on this point.Also, something else to bear in mind, is that if your type has members that are disposable, your type should either implement
IDisposable
(unless the lifecycle of those members is managed by another type, which obviously might get messy), or, if you only use such members in one method, or to implement one particular piece of functionality, you should consider making them local variables/parameters in the methods that use them.Dispose 模式不保证哪些对象将调用哪些其他对象的 Dispose;有时可能会发生,但您不应该在意。相反,您有责任确保为所有 IDisposable 对象调用 Dispose()。最好的方法是使用
using
语句。例如:The Dispose pattern doesn't make any guarantees about which objects will call Dispose on which other objects; it may happen sometimes, but you shouldn't care. Instead, it's your responsibility to make sure Dispose() is called for all IDisposable objects. The best way to do that is with the
using
statement. For example:我对“在finally块中,手动处理的对象是在类级别设置的对象”这句话感到困惑。在类级别设置的对象是指字段吗?您可能不应该在普通方法中处理它们,因为这样字段的生命周期是不可预测的,并且取决于您碰巧调用了哪些方法。最好实现 IDisposable 并在 Dispose 方法中释放字段。
I am puzzled by the statement "In the finally block, the objects which are manually disposed of are those which are set at the class level." By objects set at the class level, do you mean fields? You probably shouldn't be disposing of these within a ordinary method, because then the life-time of the fields is unpredictable, and depends on which methods you happened to have called. It would be better to implement IDisposable and dispose of fields in your Dispose method.
Using 语句可能有帮助吗?
Might the Using statement help?