The question whether “I need to Dispose some object” appears fairly often in newsgroup, wrong answers and myths appear even more often. So I thought of writing my comments on the issue – it is not supposed to be a detailed and complete reasoning and I won’t dig into garbage collection more than necessary.
(Spoiler ahead) if you don’t want to read the entire post here is the answer: Do dispose everything that implements IDisposable. IDisposable is a contract and it means I need disposing.
From this point on I will assume that Dispose is properly implemented (Dispose is just an interface method that has to be implemented by developer – it is not some sort of magic method).
What do I (possibly) gain by calling Dispose by code (note that Dispose is automatically called on all controls and components placed on WinForms Form or UserControl):
- The most important aspect of Dispose implementation: release of unmanaged resources. While Dispose is called from a finalizer, too, there are problems leaving it to finalizer – it might be delayed quite a bit (you certainly don’t want to hold a lock on a resource for days, do you) and it might not be called at all or it might be interrupted before end – finalization is much more delicate process.
- If a class implements a finalizer, than Dispose implementation will remove the object from the finalization queue thus saving memory and CPU cycles. You see, garabage collector will place such objects, once they are not in live objects graph anymore, in a finalization queue and it will (or it may not) invoke their finalizers before removing the object from memory and this might be a costly operation. Relatively speaking of course.
- it will release references to other objects and thus allow sooner garbage collection of them.
Pretty clear, isn’t it? So, what are the myths and attitudes holding people back from calling Dispose:
- Class X is derived from class Y that implements IDisposable but it does nothing within Dispose. Calling Dispose on class X would just waste CPU cycles.
There are several problems against such thinking.
- Are you sure that the Dispose of class Y does nothing at all? Let’s take DataTable for an example – it derives from MarshalByValueComponent. Common perspective is that DataTable does not hold unmanaged resources nor it does MarshalByValueComponent. While that’s true (Dispose won’t release any unmanaged resource) there is another feature everybody seems missing – point 2: MarshalByValueComponent implements a finalizer and object is removed from finalizing queue imeediately when Dispose is called thus saving CPU cycles.
- Even if Dispose really doesn’t do anything, who exactly guarantees that the implementation won’t change in future? If such change occurs at some point in time you’r application might start to behave strangely due to ignoring Dispose. And pinpointg these kind of problems is not exactly an easy process.
- If Dispose really doesn’t do anything then CPU cycles won’t be lost. At least not in significant extent.
- Lack of knowledge that dispose has to be called/being lazy.
I guess developers needs more education.
- Calling Dispose is messing with garbage collector and won’t do any good.
Yeah, well, see my list above.
- “Cleaning memory takes time and gives nothing back. So let it be done in the proper time, when there is nothing else to be done, something the GC is standard doing.“
Calling Dispose has nothing to do with cleaning the managed memory (it might just speed up a bit the process, as described in point 3). It has everything to do with cleaning unmanaged memory though. Actually Dispose by itself doesn’t do anyhting. It is just a method that is left to developer to implement.
- “Calling Dispose does not release memory. It marks the object instance as “unused” so the GC can release the memory back to the pool.“
Wrong from many point of views.
- It might release unamnaged memory.
- It doesn’t mark anything at all by itself. It just disposes child objects and releases unmanaged memory. It doesn’t affect the GC in any way for the object Dispose is being called. The implementation should remove object from the finalization queue if it implements a finalizer – thus GC will take less time for removing the object from memory.
I am sure that I’ll add more myths and wrong decisions in the future. The above ones are just from top of my head and from a recent thread in adonet newsgroup. And I have yet to hear a good argument against disposing.
The bottom line is: do dispose everything that implements IDisposable. No excuses.
And the question is whether you are a good guy or a bad guy by not disposing resources.