January 13, 2022
How to cleaning up unmanaged resources in .NET
Unfortunately, we need to release yourself unmanaged resources (such as file handles, network connections and database connections) so this article describes for cleaning up unmanaged resources in .NET.
The following are mechanisms to automate the freeing of unmanaged resources:
- Implementing the System.IDisposable interface in your class and declaring a destructor (or Finalizer) as a member of your class.
- Using statement.
Lets start about it and .NET introduced some good ways to handle unmanaged object's memory.
Implementing the System.IDisposable and Finalizer
When a class implements it, normally tells you that the class has unmanaged resources that should be released in a deterministic manner.
Implement Dispose using 'SafeHandle' Class
It is inbuilt abstract class which has 'CriticalFinalizerObject' and 'IDisposable' interface has been implemented
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
class SafeHandleDispose : IDisposable { // Take a flag to check if object is already disposed bool bDisposed = false; // Create a object of SafeHandle class SafeHandle objSafeHandle = new SafeFileHandle(IntPtr.Zero, true); // Dispose method (public) // Implement IDisposable. // Do not make this method virtual. // A derived class should not be able to override this method. public void Dispose() { Dispose(true); // This object will be cleaned up by the Dispose method. // Therefore, you should call GC.SuppressFinalize to // take this object off the finalization queue // and prevent finalization code for this object // from executing a second time. GC.SuppressFinalize(this); } // Dispose method (protected) // Dispose(bool disposing) executes in two distinct scenarios. // If disposing equals true, the method has been called directly // or indirectly by a user's code. Managed and unmanaged resources // can be disposed. // If disposing equals false, the method has been called by the // runtime. Only unmanaged resources can be disposed. protected virtual void Dispose(bool disposing) { if (bDisposed) return; if (disposing) { // Dispose using overriding the SafeHandle objSafeHandle.Dispose(); // Free any other managed objects here. } // Free any unmanaged objects here. bDisposed = true; } }
Implement Dispose using overriding the 'Object.Finalize' or destructor method
This method is clean unmanaged resources used by particular object before it is destroyed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
class FinalizeDispose : IDisposable { // Flag: Has Dispose already been called? bool bDisposed = false; // Dispose method (public) // Implement IDisposable. // Do not make this method virtual. // A derived class should not be able to override this method. public void Dispose() { Dispose(true); // This object will be cleaned up by the Dispose method. // Therefore, you should call GC.SuppressFinalize to // take this object off the finalization queue // and prevent finalization code for this object // from executing a second time. GC.SuppressFinalize(this); } // Dispose method (protected) // Dispose(bool disposing) executes in two distinct scenarios. // If disposing equals true, the method has been called directly // or indirectly by a user's code. Managed and unmanaged resources // can be disposed. // If disposing equals false, the method has been called by the // runtime. Only unmanaged resources can be disposed. protected virtual void Dispose(bool disposing) { if (bDisposed) return; if (disposing) { // Free any other managed objects here. } // Free any unmanaged objects here. bDisposed = true; } // Dispose using overriding the 'Object.Finalize' or destructor ~FinalizeDispose() { Dispose(false); } }
Using statement
It's extremely useful and used in the daily development of many projects. It defies the scope of object and will be disposed of within its block. Only use where or which class has an implementation of the IDisposable interface. We can also define multiple objects in the using statement.
Let continues above implementing the System.IDisposable's example with Using statement
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
class Program { static void Main(string[] args) { // Using statement to handle SafeHandleDispose using (SafeHandleDispose safeHandleDispose = new SafeHandleDispose()) { // Do something else } // Using statement to handle FinalizeDispose using (FinalizeDispose finalizeDispose = new FinalizeDispose()) { // Do something else } } }
That's it for now. Keep coding and enjoy exploring !!!
I’m glad you’re here. I like the simple so I created this minimalist site to share what I’ve learned interesting during my journey in technologies and in life. Keep coding and enjoy exploring !!!