调用 Dispose() 与对象超出范围/方法完成时的比较

发布于 2024-08-13 04:30:35 字数 543 浏览 10 评论 0原文

我有一个方法,里面有一个 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

许你一世情深 2024-08-20 04:30:35

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

尽管许多 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 a using block.

苏璃陌 2024-08-20 04:30:35

您应该使用 using {...} 块将 IDisposable 对象包装在 - Dispose() 方法中(对于 SqlDataReader,该方法传递给 Close( ) 方法)将在 using 块结束时被调用。如果您不使用 using,则该对象在超出范围时将不会被自动处置 - 这将取决于对象终结器(如果有的话)当资源被垃圾收集时将其清除

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

You should use a using {...} block to wrap your IDisposable objects in - the Dispose() method (which for SqlDataReader passes off to the Close() method) will be called when the using block ends. If you do not use using, 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

using (SqlDataReader aReader = aCommand.ExecuteReader())
{
    // ... do stuff
}   // aReader.Dispose() called here
扭转时空 2024-08-20 04:30:35

我同意以上所有内容。您应该确保自己调用 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 the using statement (you can also do this yourself in the finally 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 their Dispose(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.

深陷 2024-08-20 04:30:35

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

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

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:

using (SqlDataReader aReader = aCommand.ExecuteReader())
{
    // your code
}
人间☆小暴躁 2024-08-20 04:30:35

我对“在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.

最近可好 2024-08-20 04:30:35

Using 语句可能有帮助吗?

Might the Using statement help?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文