Objects are freed automatically by the garbage collector (GC). However, you can control some of this behavior by using Dispose or a finalizer.
If you want to explicitly release resources such as file handles, mutexes, and so on, you can provide a public function called Dispose or Close, which will do this on demand. If you do write this function, you should call SuppressFinalize if you have a finalizer method, so the GC does not try to free the resources twice. To use this method, you must inherit from IDisposable.
| Note |
If you have derived the class, make sure to call the base class Dispose method. |
The finalizer (~classname) method is called by the GC asynchronously when the object is being destroyed. It allows you to customize the destruction of the object when called by the GC. It is extremely important to remember that when you use this method, your object will always survive the first garbage collection and will not be freed until the next garbage collection cycle.
| Caution |
Use the finalizer only to release unmanaged resources, and avoid doing this if you can. The order in which objects that have a finalizer are freed by the GC is not defined. This makes freeing managed resources in the finalizer dangerous. You can use Performance Monitor counters to determine the effect of using finalizers in your code. Use FinalizationSurvivors to determine the unmanaged resources that are consuming memory. Use Promoted Finalization-Memory from Gen X to determine the number of bytes that were promoted to this generation (note that this specific counter is not cumulative; it's reset with each sample). |
The following example demonstrates destroying objects.
using System; namespace Client.Chapter_5___Building_Your_Own_Classes { class DTOR: IDisposable { public static int[] MyIntArray; private static int ObjectCount = 0; private bool Disposed = false; static void Main(string[] args) { MyIntArray = new int[10]; ObjectCount++; } //Used to clean up and free unmanaged resources. //Never mark this class as virtual, because you do not want // derived classes to be able to override it. public void Dispose() { //If this class is derived, call the base //class Dispose. base.Dispose(); //Call the overloaded version of Dispose Dispose(true); //Tell the CLR not to run the finalizer this way. //You do not free unmanaged resources twice. GC.SuppressFinalize(this); } //If the user calls Dispose, both managed and unmanaged // resources are freed. //If the finalizer is called, only unmanaged resources are freed. private void Dispose(bool disposing) { if(!this.Disposed) { if(disposing) { //Free any managed resources. } //Free unmanaged resources. } Disposed = true; } //This finalizer method is called by the GC, //not the user. The net result of having this is that //the object will always survive the first GC cycle and //will be collected the next time GC1 is collected. ~DTOR() { Dispose(false); } } }