应该“处置"仅用于包含非托管资源的类型? [英] Should "Dispose" only be used for types containing unmanaged resources?

查看:18
本文介绍了应该“处置"仅用于包含非托管资源的类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近和一位同事讨论了 Dispose 的值和实现 IDisposable 的类型.

I was having a discussion with a colleague recently about the value of Dispose and types that implement IDisposable.

我认为为应该尽快清理的类型实现 IDisposable 是有价值的,即使没有要清理的非托管资源.

I think there is value in implementing IDisposable for types that should clean up as soon as possible, even if there are no unmanaged resources to clean up.

我的同事想法不同;如果您没有任何非托管资源,则无需实施 IDisposable,因为您的类型最终会被垃圾回收.

My colleague thinks differently; implementing IDisposable if you don't have any unmanaged resources isn't necessary as your type will eventually be garbage collected.

我的论点是,如果您有一个想要尽快关闭的 ADO.NET 连接,那么实现 IDisposableusing new MyThingWithAConnection() 将使感觉.我的同事回答说,ADO.NET 连接实际上是一个非托管资源.我对他的回复是一切最终都是非托管资源.

My argument was that if you had an ADO.NET connection that you wanted to close as soon as possible, then implementing IDisposable and using new MyThingWithAConnection() would make sense. My colleage replied that, under the covers, an ADO.NET connection is a unmanaged resource. My reply to his reply was that everything ultimately is an unmanaged resource.

我知道推荐的一次性模式,其中如果调用了 Dispose,则释放托管和非托管资源,但如果通过终结器/析构函数调用,则仅释放非托管资源(并在不久前发表了关于如何提醒消费者不当使用您的 IDisposable 类型)

I am aware of the recommended disposable pattern where you free managed and unmanaged resources if Dispose is called but only free unmanaged resources if called via the finalizer/destructor (and blogged a while ago about how to alert consumers of improper use of your IDisposable types)

所以,我的问题是,如果你有一个不包含非托管资源的类型,是否值得实现 IDisposable?

So, my question is, if you've got a type that doesn't contain unmanaged resources, is it worth implementing IDisposable?

推荐答案

IDisposable 有不同的有效用途.一个简单的例子是持有一个打开的文件,当您不再需要它时,您需要在某个时刻将其关闭.当然,您可以提供一个方法 Close,但将它放在 Dispose 中并使用像 这样的模式 using (var f = new MyFile(path)) {/*处理它*/} 会更安全.

There are different valid uses for IDisposable. A simple example is holding an open file, which you need to be closed at certain moment, as soon as you don't need it any more. Of course, you could provide a method Close, but having it in Dispose and using pattern like using (var f = new MyFile(path)) { /*process it*/ } would be more exception-safe.

一个更流行的例子是持有其他一些 IDisposable 资源,这通常意味着您需要提供自己的 Dispose 才能同时处置它们.

A more popular example would be holding some other IDisposable resources, which usually means that you need to provide your own Dispose in order to dispose them as well.

一般来说,只要你想对任何东西进行确定性销毁,你就需要实现 IDisposable.

In general, as soon as you want to have deterministic destruction of anything, you need to implement IDisposable.

我的观点和你的不同之处在于,我在某些资源需要确定性销毁/释放时立即实施IDisposable,而不是尽快.在这种情况下,依靠垃圾收集不是一种选择(与您同事的说法相反),因为它发生在不可预测的时刻,实际上可能根本不会发生!

The difference between my opinion and yours is that I implement IDisposable as soon as some resource needs deterministic destruction/freeing, not necessary as soon as possible. Relying on garbage collection is not an option in this case (contrary to your colleague's claim), because it happens at unpredictable moment of time, and actually may not happen at all!

任何资源在掩护下不受管理的事实并不意味着什么:开发人员应该考虑何时以及如何处置该对象是正确的",而不是它如何在掩护下工作".无论如何,底层实现可能会随着时间而改变.

The fact that any resource is unmanaged under the cover really doesn't mean anything: the developer should think in terms of "when and how is it right to dispose of this object" rather than "how does it work under the cover". The underlying implementation may change with the time anyway.

事实上,C# 和 C++ 之间的主要区别之一是没有默认确定性销毁.IDisposable 来缩小差距:您可以订购确定性销毁(尽管您无法确保客户端正在调用它;与 C++ 中的相同方式,您无法确定客户端调用 delete 在对象上).

In fact, one of the main differences between C# and C++ is the absence of default deterministic destruction. The IDisposable comes to close the gap: you can order the deterministic destruction (although you cannot ensure the clients are calling it; the same way in C++ you cannot be sure that the clients call delete on the object).

小补充:确定性释放资源和尽快释放资源之间实际上有什么区别?实际上,这些是不同的(尽管不是完全正交的)概念.

Small addition: what is actually the difference between the deterministic freeing the resources and freeing them as soon as possible? Actually, those are different (though not completely orthogonal) notions.

如果要确定地释放资源,这意味着客户端代码应该有可能说现在,我想释放这个资源".这实际上可能不是释放资源的可能的最早时刻:持有资源的对象可能已经从资源中获得了它需要的一切,因此它可能已经释放了资源.另一方面,即使在对象的 Dispose 运行之后,对象也可能选择保留(通常是非托管的)资源,仅在终结器中清理它(如果持有资源太长时间不会提出任何问题).

If the resources are to be freed deterministically, this means that the client code should have a possibility to say "Now, I want this resource freed". This may be actually not the earliest possible moment when the resource may be freed: the object holding the resource might have got everything it needs from the resource, so potentially it could free the resource already. On the other hand, the object might choose to keep the (usually unmanaged) resource even after the object's Dispose ran through, cleaning it up only in finalizer (if holding the resource for too long time doesn't make any problem).

所以,为了尽快释放资源,严格来说,Dispose 是不必要的:对象可以在意识到自己释放资源时立即释放资源不再需要资源.然而,Dispose 提供了一个有用的提示,即不再需要对象本身,因此如果合适的话,资源可能会在此时被释放.

So, for freeing the resource as soon as possible, strictly speaking, Dispose is not necessary: the object may free the resource as soon as it realizes itself that the resource is not needed any more. Dispose however serves as a useful hint that the object itself is not needed any more, so perhaps the resources may be freed at that point if appropriate.

还有一个必要的补充:需要确定性释放的不仅是非托管资源!这似乎是这个问题的答案中意见分歧的关键点之一.一个人可以有纯粹的想象结构,这可能需要确定性地释放.

One more necessary addition: it's not only unmanaged resources that need deterministic deallocation! This seems to be one of key points of the difference in opinions among the answers to this question. One can have purely imaginative construct, which may need to be freed deterministically.

例如:访问某些共享结构的权利(想想 RW-lock),一个巨大的内存块(想象你正在手动管理一些程序的内存),一个使用其他程序的许可证(想象你不能运行超过X 同时复制某些程序)等.这里要释放的对象不是非托管资源,而是 right 做/使用某事,这是您程序的纯粹内部构造逻辑.

Examples are: a right to access some shared structure (think RW-lock), a huge memory chunk (imagine that you are managing some of the program's memory manually), a license for using some other program (imagine that you are not allowed to run more than X copies of some program simultaneously), etc. Here the object to be freed is not an unmanaged resource, but a right to do/to use something, which is a purely inner construct to your program logic.

小补充:这里是 [ab] 使用 IDisposable 的简洁示例列表:http://www.introtorx.com/Content/v1.0.10621.0/03_LifetimeManagement.html#IDisposable.

Small addition: here is a small list of neat examples of [ab]using IDisposable: http://www.introtorx.com/Content/v1.0.10621.0/03_LifetimeManagement.html#IDisposable.

这篇关于应该“处置"仅用于包含非托管资源的类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆