Without having read your article in-depth (you may already have covered this?) - I would like to give my 2 cents.
I have been working with this pattern alot myself, and have come across an issue that one has to take into account when writing their "CleanUp"-code:
The sequence of which the "Finalize" method is called is non-deterministic:
1) Say you have object A that is referencing object B
2) object A's CleanUp() calls Dispose on object B
With the above design - you may experience that the garbage collector chooses to call Finalize on object B before object A even though object A reference object B.
Solution: Always check whether or not your object has already been disposed in your "CleanUp"-code.
/Michael
Need a 0 false positive SPAM filter? Try the free, industry leading spam filters from SPAMfighter
With the above design - you may experience that the garbage collector chooses to call Finalize on object B before object A even though object A reference obj
Which is why the standard pattern has a disposed flag, which allows you to distinguish Dispose calls from finalizer calls. If the call is from the finalizer, you can skip cleanup of managed objects implementing a finalizer.
I agree to your comments and i have updated the code with the disposing flag. I was trying to provide a more shorter way. But then i realized performance can not have shortcuts.
Yes, the GC is such a undetermestic beast a flag is essential.
Let me know if the code is fine.
Visit my 500 videos on WCF,WPF,WWF,Silverlight,UML design patters @ http://www.questpond.com
There are however a few items that I have been unable to fully grasp despite a lot of searching on the net and as you obviously have the gift of providing understandable explanations of otherwise complex issues, I wonder if you could expand on:
1. Destructors.
Exactly what does a destructor do? I would have guessed it destructs everything constructed within the class but obviously not. The destructor appears almost in no class that I have ever come accross on the net.
2. CleanUp().
What has to be 'cleaned up'. All anyone says is 'unmanaged code' but what exactly is unmanaged code? I found out about static variables the hard way.
3. GC.SuppressFinalize(this)
If I forget to CleanUp() some 'item', will it never be 'collected' by the GC?
I appreciate the above is not actually part of your article however it would help me to understand your article much better and put to bed some matters that have been baffling me for a long time.
1. Destructors.
Some good info available at these threads
http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/f73ad923-ffd5-4f16-a0bf-1f27b71f952f
In short there is no need for a default destructor unless you are dealing with these unmanaged objects.
2. CleanUP()
Some examples of unmanaged resources are network connections, file streams, database connection etc.
3. GC.SuppressFinalize(this)
The stackoverflow.com has some good responses to this...
http://stackoverflow.com/questions/151051/when-should-i-use-gc-suppressfinalize
These are not direct answers to your questions but just some pointers for reference.
1 - In C#, a destructor will be compiled into Finalize() method. Destructor is used to perform resource cleanup. You need destructors only in those classes that has some resources to cleanup. MSDN says, finalization is costly and you should avoid it if possible.
Any class that holds other disposable objects or work directly with unmanaged code is a good candidate for writing destructor and implementing dispose pattern.
2 - Any resource an object holds should be cleaned up once done. If your class holds some resources that needs clean-up, you should write destructor and implement IDispose interface. Writing Dispose() method is for deterministic resource clean-up and destructor is for garbage collector.
Un-managed code is something that CLR won't have control. For e.g: P/Invoke call to a native library.
3 - GC.SuppressFinalize() will suppress the execution of finalize methods. This is useful when you have already cleaned-up the resources by calling dispose.
Glen Harvy wrote:
If I forget to CleanUp() some 'item', will it never be 'collected' by the GC?
Depends on what kind of resources your class holds. Consider the following class,
class Logger
{
FileStream stream = /* ... */// Other code
}
In this case, even if you forgot to call dispose on stream , it will get collected when nothing is referring the variable. But this is not the case when you use a handle directly. In such cases, you need to explicitly remove it and GC can't clean it.
Probably i should have put a pre-requiste about what should be know before reading this article. My main focus was on the issues of perfomance hit due to GC.
For the coming articles i will try to keep pointers for beginners as well.
Visit my 500 videos on WCF,WPF,WWF,Silverlight,UML design patters @ http://www.questpond.com
I appreciate that your article was intended to discuss performance but with a couple more well written sentences (for which you appear to have the skills), the article would have been self-contained and would have provided me with all I needed to know on the subject.
It is difficult to discuss technical isues without using jargon however I do believe many articles are written to prove how much the author knows, not to provide the answers to the 'student'.
Thank you for your efforts. Keep up the good work.