In computer science, garbage collection (GC) is a form of automatic memory management. The garbage collector attempts to reclaim memory that was allocated by the program, but is no longer referenced; such memory is called garbage. Garbage collection was invented by American computer scientist John McCarthy around 1959 to simplify manual memory management in Lisp.
This series of articles discuss the Garbage Collection in .NET.
A - Introduction
This article will discuss Cleaning Up Unmanaged Resources: manage and clean up unmanaged resources.
The content of this article:
- A - Introduction
- B - Two ways to clean the unmanaged resource,
- C - Automatic way by Finalizer and GC
- D - Manual Way by Dispose Pattern
- 1: IDisposable interface;
- 2: Dispose() method;
- 3: GC.SuppressFinalize method;
- 4: Override the Object.Finalize method
- 5: Disposable Types;
- 6: Consumer of the Desposable Type;
- E - Summary
B - Two ways to clean the unmanaged resource
- Automatic way by Finalizer and GC
- Manual way by Dispose Pattern

C - Automatic way by Finalizer and GC
- The Finalize method is called automatically after an object becomes inaccessible, unless you have protected the object against finalization.
- The Finalize method is called as the very last operation before the application terminates, and it is nondeterministic. Normally, most of Finalize methods will run at some other point during the run of the application and not at the very end.
- Destructor
- C# doesn’t strictly support destructors
- C# does support overriding the Object.Finalize method that is syntactically identical to a destructor as ~Classname.
- Compiler wraps all code in the ‘destructor’ (finalizer) or the Finalize override in a try block and the compounding finally block is calling the base class object.Finalize
- Drawbacks of using Finalizer
- The finalizer is called when the GC detects that an object is eligible for collection. This happens at some undetermined period of time after the resource is not needed anymore. The delay between when the developer could or would like to release the resource and the time when the resource is actually released by the finalizer might be unacceptable.
- When the CLR needs to call a finalizer, it must postpone collection of the object’s memory until the next round of garbage collection (the finalizers run between collections). This means that the object’s memory (and all objects it refers to) will not be released for a longer period of time.
D - Manual Way by Dispose Pattern
- Implement the dispose pattern. This requires that you provide an IDisposable.Dispose implementation to enable the deterministic release of unmanaged resources. A consumer of your type calls Dispose when the object (and the resources it uses) is no longer needed. The Dispose method immediately releases the unmanaged resources.
- Provide a way for your unmanaged resources to be released in the event that a consumer of your type forgets to call Dispose. There are two ways to do this,
- Override the Object.Finalize method (in concept).
- Use a safe handle to wrap your unmanaged resource (in practice).

However, Microsoft warns that this way "can be complex and error-prone". In practice, we should use Safe handle method.
SafeHandle calss in short (also: Essential C# 4.0 P824 ):
- SafeHandle. ReleaseHandle method is guaranteed to be called only once and only if the handle is valid as defined by the IsInvalid property.
- lf SafeHandle class customer calls the class Dispose() method, it will invoke the SafeHandle. ReleaseHandle method; otherwise
- The garbage collector will call ReleaseHandle after normal finalizers have been run for objects that were garbage collected at the same time.
- i.e., SafeHandle class does the same as Object.Finalize method does --- that will be invoked by Garbage collector automatically, if not run once. See the code sample at SafeHandle and Dispose
- 1: IDisposable interface;
- 2: Dispose() method;
- 3: GC.SuppressFinalize method;
- 4: Override the Object.Finalize method
- 5: Disposable Types;
- 6: Consumer of the Desposable Type;
- public interface IDisposable
- {
- void Dispose();
- }
- public void Dispose()
- {
- ...... // Dispose the unmanaged resources
- }
- public void Dispose()
- {
- ...... // Dispose the unmanaged resource
- GC.SuppressFinalize(this);
- }
- public class MyClass
- {
- ~MyClass()
- {
- // Do unmanaged resource clean up here
- Console.WriteLine("In destructor");
- }
- }
- public class MyClass
- {
- protected override void Finalize()
- {
- // Do unmanaged resource clean up here
- }
- }

- public class MyClass : IDisposable
- {
- private string name;
- public MyClass(string name) { this.name = name; }
- override public string ToString() { return name; }
- // call Dispose() in Finalizer, i.e., 'Destructor'
- ~MyClass()
- {
- Dispose();
- Console.WriteLine("~Thing()");
- }
- // Implementation of IDisposable.
- // Call the virtual Dispose method.
- // Suppress Finalization.
- public void Dispose()
- {
- Console.WriteLine("Dispose()");
- GC.SuppressFinalize(this);
- }
- }
- public class GarbageDisposalApp
- {
- [STAThread]
- public static void Main(string[] args)
- {
- DoSomething();
- Console.WriteLine("end of Main");
- Console.ReadLine();
- }
- public static void DoSomething()
- {
- MyClass t = new MyClass("Foo");
- Console.WriteLine(t);
- t.Dispose(); // toggle this to see the difference
- t = null;
- GC.Collect();
- GC.WaitForPendingFinalizers();
- }
- }
- The Dispose Pattern is intended to standardize the usage and implementation of finalizer and the IDisposable interface to free foreign resources.
- The main reason for the Dispose pattern is to enable the client of an object to Dispose it manually, while making sure that the object is Disposed exactly once during its lifetime.
E - Summary
- Basically, you need to call Dispose from the destructor, and in the Dispose you should Suppress the Finalize
- When you properly implement a Dispose method, the Finalize method becomes a safeguard to clean up resources if the Dispose method is not called.
- The Finalize method will be called at some point during the run of the application before the very end point, automatically. The dispose method must be invoked manually.
- To avoid after running the dispose manually and then run the finalizer automatically again, or missing to run the dispose, we should call the dispose method from the finalize method, and suppress the Finalize method by GC.SuppressFinalize from the dispose method.

Join the conversation! Your thoughts help the community grow.