The first thing to be clear about is that Dispose() has absolutely NOTHING to do with memory. The IDisposable pattern is entirely about cleaning up unmanaged resources... that is, cleaning up anything and everything except memory.
Component.Dispose()
is documented here:
http://msdn.microsoft.com/en-us/library/3cc9y48w.aspx
Notice the following except:
After calling Dispose, you must release all references to the Component so the garbage collector can reclaim the memory that the Component was occupying.
Again, we see that Dispose()-ing an object is a separate issue from releasing memory.
In the case of SqlConnection
, there is an inheritance heirarchy at work. There is an empty Dispose()
method on the Component
type itself (empty methods are legal). The method is empty, because the base class doesn't itself have any unmanaged resources to worry about. The SqlConnection
type overrides the base implementation, so that it will close the connection to the server.
Now let's talk about finalizers. Finalizers also have nothing to do with memory, except that they are called by the garbage collector. The purpose of a finalizer is to release unmanaged (non-memory) resources when an object is collected. If you're building a class that uses an abundant unmanaged resource, such that there is no risk for contention or exhausting the resource, a finalizer is enough by itself, and Dispose() serves no purpose. However, nearly all computing resources have some degree of scarcity, such that you may not want to wait on the garbage collector before releasing them. The garbage collector might not collect an object for some time, and so the Dispose() pattern exists to provide a way to release unmanaged resources in a timely, predictable way.
The goods news is that, most of the time, you don't need to worry about finalizers. You only need to implement a finalizer if you are building an entirely new kind of unmanaged resource. As an example, if you have a type in your program that manages your connection to a Sql Server database by wrapping the SqlConnection class, you don't need a finalizer. This may be a new class, but the the SqlConnection type will ultimately handle releasing your database connection. You should, however, implement or make use of IDisposable in your type, so that the connections it manages will be released promptly. On the other hand, if you are building an entirely new kind of database engine to compete with Sql Server, or were to re-implement the Sql Server connection protocols from scratch, you would want a finalizer.
Sometimes, your Dispose() method will need to suppress finalization. You might do this if, for example, trying to free your unmanaged resource a second time, after you've already disposed it, would cause an unnecessary exception.
I think I've covered most of the points from your three questions, but there are a few things still to address:
it looks "public void Dispose() { }". But when I just write a class and declare a method without any body, it gives me compile time error saying, I should define the body
That method has a body. { }
is the body of the method. It's just that it's empty.
where is [SqlConnection.Dispose()] actually implemented?
You're looking at the IDE. That only shows method declaration and a basic description. There's more code there. If you really want it, the full .Net source code is available.
They also use Kernel32 method CloseHandle for unmanaged resource. What is the use of this method?
That's just a method specific to disposing that particular kind of resource. Part of the purpose of the IDisposable pattern is providing a standard place to put this kind of thing, so that you as programmer don't need to know about that stuff to correctly dispose an object.
Component
does not implementDisponse
? The documentation clearly shows that it does. msdn.microsoft.com/en-us/library/… – shf301