Garbage Collector in DotNet is in-deterministic which means that we can never be sure when the garbage collector will be invoked (of course, unless and until we explicitly invoke it).
Now there might be scenarios in which we need to release certain resources held by an object (like a database connection) once the object is no longer in use without having to wait for the Garbage Collection to happen.
We have destructors in C#. But unlike destructors in C++ which are automatically called when an object is in no longer in use (by using delete operator), in C# destructors are nothing but finalize methods in disguise, with a call to base class’s finalize method.
Finalize method is called during garbage collection by garbage collector. Hence, we cannot rely only on C# destructors to explicitly release resources, as finalize methods on objects may never be called altogether (if the program terminates abnormally) or might be called only when the program terminates (in a normal way).
Hence it is always a good practice to implement IDisposable interface in such cases and to write code to release resources explicitly in the Dispose() method.
We know that the Dispose method of a class has always to be called by the developer explicitly when an instance of that class is no longer in use. Now, what if the developers who use our class forget to call the Dispose() method? Hence, it is also good practice to write the same code in C# destructor too, so that at least the garbage collector will release the resources, whenever it is invoked (if at all it gets invoked!!)
Now what if the developer also calls the dispose() method and garbage collector also gets invoked and calls the finalize method on such objects. Well, in that case garbage collector might get run time exceptions while calling finalize method as the Dispose() method would have already released the resources held by the object.
Well, we know that the Garbage Collector ignores any exceptions which occur while calling a finalize method on an object being garbage collected and will terminate the finalize method execution. But we should remember that, calling finalize methods on objects during garbage collection is a costly process and so are exceptions.
So we should ensure that if dispose() method is called on an object then garbage collector does not invoke finalize method on that object. This could be achieved by calling System.GC.SuppressFinalize() method at the end of Dispose() method. SuppressFinalize() tells the Garbage Collector not to call finalize method on that object.
Another interesting feature in C# related to Garbage Collection is the using keyword. Few know that there is another using keyword in C# other than the one used to import namespaces.
This second using keyword is used to define the scope of an object implementing the IDisposable interface. What this does is that it automatically calls the Dispose() method when the object goes out of the scope defined in the using block. This means that the developer need not call Dispose() method explicitly. All he needs to do is to define the scope of the object.
Here is an sample code snippet.
SqlConnection con = new SqlConnection(); using (con) { //your code goes here }
In the above example as soon as the execution reaches the closing braces, Dispose() method is automatically called. Note that using keyword can be applied only to those objects whose class implements the IDisposable interface.