1
votes

Well I am trying to understand the release of memory procedures which can be done explicitly by code.

I see in the below MS thread that Dispose method is implemented in Component class. Here I have three doubts.

  1. Component class derives from IDisposable, however, in this class library, I find it is not implementing the method Dispose and not even 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 or make it abstract. Why is this difference?

  2. I generally used this way, say for example, "connection.Dispose();" in the finally block to dispose sqlconnection. I understand that, SqlConnection is derived from DBConnection which in turn in derived from Component. When I looked at the Component class, I see just the declaration of the method "public void Dispose();" Then where it is actually implemented?

  3. I also see some code that specifically implements like the one given in the MS website below. They declare a bool variable for Dispose status and have a new Dispose method where they call the Component Dispose on the object. They also use Kernel32 method CloseHandle for unmanaged resource. What is the use of this method? I never used this for my SqlConnection (Which is also an unmanaged resource) while disposing it.

http://msdn.microsoft.com/en-us/library/system.gc.suppressfinalize(v=vs.110).aspx

Could somebody please help me understand the three questions above in a brief way too. I am just learning all these. Thank you

2
Fwiw, Dispose() has NOTHING to do with memory.Joel Coehoorn
@JoelCoehoorn: Disposes the unmanaged and managed resources and reclaims memory is what I learnt. The MS website says "Objects that implement the IDisposable interface can call this method from the IDisposable.Dispose method to prevent the garbage collector from calling Object.Finalize on an object that does not require it."Jasmine
Where are you seeing that Component does not implement Disponse? The documentation clearly shows that it does. msdn.microsoft.com/en-us/library/…shf301
Then you learned wrong. The Garbage collector is responsible for cleaning up memory from an object, even if you dispose it.Joel Coehoorn
You are just getting confused by the way the IDE shows you info about classes in the .NET framework, like Component. It does not show you the source code, you don't have the source code for all the .NET framework classes. Microsoft has it. It just shows you the "outline" of the class, just the declarations. Same thing you see in Object Browser. You don't write C# code that way yourself. Your questions are otherwise well covered in any intermediary book about the .NET framework.Hans Passant

2 Answers

1
votes

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.

3
votes

Firstly:

public void Dispose() { }

has a body - it is just an empty one. There is no difference here. Actually, though Component.Dispose is:

public void Dispose()
{
    Dispose(true);
    GC.SuppressFinalize(this);
}

The idea is that you override the protected virtual void Dispose(bool disposing) method if you want to add logic.

Secondly, if you are calling connection.Dispose() like that, then you are doing it wrong. You should be using a using block:

using(var conn = ...)
{
    conn.Open();
    using(var cmd = conn.CreateCommand())
    {
        // etc etc
    }
    // look ma, no finally
}

Your third point, and the MSDN article you cite, is simply an example of when you might actually need to do this. The CloseHandle method is simply an illustration of an unmanaged resource. This is key, because you don't use finalizers to clean up managed resources - only unmaged. As such, an example that involves an unmanaged handle is simple an excuse to illustrate:

  • calling Dispose(false) from a finalizer
  • override the Dispose(bool) method
  • having some code (the handle) get cleaned up from both the finalizer and disposal (separately, Dispose(false) and Dispose(true))
  • having some code that only gets executed for the Dispose(true) case - i.e. onward disposal