析构函数VS IDisposable的?函数、VS、IDisposable

2023-09-02 11:49:26 作者:满窗星星

我已经知道了在C#处理对象/ IDisposable接口和析构函数,但对我来说,他们似乎做同样的事情?

I've read about disposing objects/IDisposable interface and destructors in C#, but to me they seem to do the same thing?

这两者之间的区别是什么?为什么我会用一个比其他?事实上,在这个例子中该code同时使用IDisposable接口和析构函数(下面的链接):

What is the difference between the two? Why would I use one over the other? In fact, in this example (link below) this code uses both the IDisposable interface and a destructor:

http://msdn.microsoft.com/en-us/library/system.idisposable.aspx

该评论说,析构函数,如果不使用定稿code,但我怎么决定什么时候使用一个比其他?

The comment says the destructor is if the finalization code is not used, but how do I decide when to use one over the other?

推荐答案

我写了一个很深入的职位,而应有助于解释关于终结,IDisposable的,当你应该使用一个或另一个:http://gregbee.ch/blog/implementing-and-using-the-idisposable-interface

I wrote a fairly in-depth post which should help to explain about finalizers, IDisposable, and when you should use one or the other: http://gregbee.ch/blog/implementing-and-using-the-idisposable-interface

可能是最有用的部分被引述如下:

Probably the most relevant part is quoted below:

当你使用非托管资源   如把手和数据库   连接,你应该确保   他们正在举行的最低金额   的时间,使用的原则   收购后期和提前释放。在C ++   释放资源典型地是   在析构函数完成,这是   确定性的点运行   在对象被删除。互联网   运行时,然而,使用垃圾   收集器(GC)清理和回收   使用对象的内存没有   再访问​​;因为这样运行在   定期则意味着点   在此你的对象是清理被   不确定的。的结果   这是析构不存在   为管理对象,因为没有   确定性的地方运行它们。

When you are using unmanaged resources such as handles and database connections, you should ensure that they are held for the minimum amount of time, using the principle of acquire late and release early. In C++ releasing the resources is typically done in the destructor, which is deterministically run at the point where the object is deleted. The .NET runtime, however, uses a garbage collector (GC) to clean up and reclaim the memory used by objects that are no longer reachable; as this runs on a periodic basis it means that the point at which your object is cleaned up is nondeterministic. The consequence of this is that destructors do not exist for managed objects as there is no deterministic place to run them.

相反析构函数,C#有   这是由执行终结   覆盖定义Finalize方法   在基类对象(虽然C#   有点混乱的是使用C ++   析构函数语法〜对象为这个)。   如果一个对象覆盖finalize   然后方法而不是被   通过GC进行收集时,它是选自   范围,GC将其置于一个终结   队列。在未来的GC周期的所有   队列终结器上运行(   在当前的单个线程   实施),并从存储器   最终确定的对象回收。其   从这个为什么你不很明显   想在一个终结清理:它   需要两个GC周期收集   对象,而不是一个,并有一个   单个线程,所有终结器   运行,而所有其他线程   暂停,所以它会伤害   性能。

Instead of destructors, C# has finalizers which are implemented by overriding the Finalize method defined on the base Object class (though C# somewhat confusingly uses the C++ destructor syntax ~Object for this). If an object overrides the Finalize method then rather than being collected by the GC when it is out of scope, the GC places it on a finalizer queue. In the next GC cycle all finalizers on the queue are run (on a single thread in the current implementation) and the memory from the finalized objects reclaimed. It's fairly obvious from this why you don't want to do clean up in a finalizer: it takes two GC cycles to collect the object instead of one and there is a single thread where all finalizers are run while every other thread is suspended, so it's going to hurt performance.

所以,如果你没有析构函数和   你不想离开清理到   终结,那么唯一的选择就是   手动,确定性,干净   向上的对象。进入了IDisposable   接口,它提供了一个标准的   为支持此功能,并   定义了一个方法,处置,   在那里你把清理逻辑   的对象。当在一个最终用   块,这个接口提供   等同的功能   析构函数。之所以最后   在code块主要是支持   IDisposable接口;这就是为什么   C ++使用简单地尝试/除非有   不需要一个最后用块   析构函数。

So if you don't have destructors, and you don't want to leave the cleanup to the finalizer, then the only option is to manually, deterministically, clean up the object. Enter the IDisposable interface which provides a standard for supporting this functionality and defines a single method, Dispose, where you put in the cleanup logic for the object. When used within a finally block, this interface provides equivalent functionality to destructors. The reason for finally blocks in code is primarily to support the IDisposable interface; this is why C++ uses simply try/except as there is no need for a finally block with destructors.