Click here to Skip to main content
6,295,667 members and growing! (15,099 online)
Email Password   helpLost your password?
Platforms, Frameworks & Libraries » .NET Framework » General     Beginner

GC 101

By Ernst Kuschke

An introduction to programming for the Garbage Collector.
C#, Windows, .NET 1.0, .NET 1.1, Visual Studio, Dev
Posted:29 Feb 2004
Views:60,363
Bookmarked:39 times
Announcements
Loading...
 
Search    
Advanced Search
printPrint   Broken Article?Report       add Share
  Discuss Discuss   Recommend Article Email
36 votes for this article.
Popularity: 6.10 Rating: 3.92 out of 5
2 votes, 5.6%
1
2 votes, 5.6%
2
4 votes, 11.1%
3
15 votes, 41.7%
4
13 votes, 36.1%
5

Introduction

I see questions regarding the GC on a daily basis. Finalize vs. Dispose is a popular topic. Let's get it in the clear.

All of us .NET programmers make use of the Garbage Collector (GC) � some without knowing so. You have to familiarize yourself with the internals of the GC if you wish to create scalable components � there is no other option. Even though it does all its bits automagically, you can harness a lot of its power by understanding three basics: Finalize, Dispose, and the Destructor protocol in managed code. I will not be going into the finer details of how the GC does its job, but rather explain how you as a programmer can (and should) optimize your objects for the GC.

Finalize

When an object is instantiated, the GC allocates memory for it on the managed heap. If the class contains a Finalize method, the object is also enlisted in the �finalisation queue�. When this object is no longer needed, its memory will be reclaimed (freed) by the GC. If the object is enlisted in the finalization queue, its Finalize method will be called before discarding of the object. The purpose of the Finalize method is to release any resources (like a database connection, or a handle on a window) that might be in use by your object.

Since the GC decides when it is best to clean up objects (and it does a damn fine job in doing so!), you have no way of telling when exactly Finalize will be called. Finalize is also a protected member and can thus not be called explicitly. Does this mean that cleaning up your object is left entirely in the hands of the GC?

Dispose

Of course not. For increased performance, it is best to cleanup your unused resources immediately after using them. For instance, as soon as you have retrieved your data through a database connection, the connection should be discarded of since it eats up system resources like memory, which could be better utilized by objects that you do in fact need. For this reason, an object can implement the Dispose method (by implementing the IDisposable interface). Calling the Dispose method on an object does two things. Firstly, it cleans up any resources that were in use by your object. Secondly, it marks the object so that the GC would not call its Finalize method when it collects it � the resources have been cleaned up already in your Dispose method. This way, you save the overhead of the GC�s call to Finalize, and you can clean up your object at the most appropriate time.

How to implement Finalize and Dispose

Now that you know the reasons for these two methods, let�s see how to implement it.

In managed code, you cannot override or even call Finalize � it is implicitly generated (in IL) by the compiler if you have a destructor for your object. In other words, the following:

~MyClass
{
    //Cleanup code here

}

Translates to the following:

protected override void Finalize()
{
    try
    {
        //Cleanup of used resources

    }
    finally
    {
        base.Finalize();
    }
}

As you can see, the method also calls Finalize on its parent type, and the parent type will call Finalize on its parent type � the whole hierarchy of your object is thus cleaned up. It is important to understand that you should only have a destructor for your class if it is really necessary, since calling Finalize, and enlisting objects that implement Finalize in the finalization queue by the GC, has significant performance implications.

The Dispose method is publicly callable. (I�ll explain the overload that accepts the boolean parameter later). Here is an example of an object that implements IDisposable:

public class MyClass : IDisposable, BaseClass
{
    bool disposed; //Indicates if object has been disposed


    //Constructor, where your resources might be instantiated

    public MyClass()
    {
        disposed = false;
        //Other Constructor code here

    }
 
    //Destructor, that would imply a Finalize method as noted above

    ~MyClass()
    {
        //Dispose is called, passing false, so that only

        //unmanaged resources are cleaned up. 

        Dispose(false);
    }

    public void Dispose()
    {
        Dispose(true);
        //Prevent the GC to call Finalize again, since you have already

        //cleaned up.

         GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        //Make sure Dispose does not get called more than once,

        //by checking the disposed field

        try
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    //Clean up managed resources

                }
                //Now clean up unmanaged resources

            }
            disposed = true;
        }
        finally
        {
            base.Dispose(disposing);
        }
    }
}

When you explicitly call Dispose() on your object, both managed- and unmanaged resources will be cleaned up. When the GC cleans your object (instead of you), only unmanaged resources will be cleaned, since the managed resources will be cleaned up by the GC when necessary.

Final Notes

Don�t reference any managed resources in your Finalize method (destructor), since Finalizers are not called in any particular fashion, and the object you reference may thus be disposed of already. In such a case, your Finalize method will fail. If you *do* reference any managed resources downward in your object hierarchy, those objects will not be finalized with the current GC collection, and performance will suffer.

When calling any method on your object, it is necessary to first check if the object has been disposed. So a method in MyClass would look like this:

//In MyClass:

public void MyMethod()
{
    if (this.disposed)
    {
        throw new ObjectDisposedException();
    }
    //Method code goes here

}

In a further article, I will dive deeper into the GC, and explain the implications of threading on your Finalize and Dispose methods.

(This article is also published on my blog.)

[Update: Check GC 102 for further notes on programming for Garbage Collection.]

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Ernst Kuschke


Member
Ernst develops software for the agricultural industry.
He moderates the SADeveloper INETA community, and gives talks on development-related stuff from time to time.
He is an MVP in Visual C#, but whilst he advocates the adoption of .NET, he is also skilled in non-Microsoft technologies.
Sometimes he chats about it.
Occupation: Web Developer
Location: South Africa South Africa

Other popular .NET Framework articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 12 of 12 (Total in Forum: 12) (Refresh)FirstPrevNext
GeneralNice article, but a small question PinmemberJaggu_Aztecsoft19:16 17 Feb '08  
GeneralHey ..this is copied from... PinmemberRavindraThakur0:59 22 Dec '06  
AnswerRe: Hey ..this is copied from... PinmemberErnst Kuschke5:38 23 Feb '09  
GeneralDoes dispose method dispose referenced objects!! PinsussGoneCase19:54 26 Oct '04  
GeneralManaged vs. Unmanaged Pinmemberdwurtz7:09 9 Mar '04  
GeneralRe: Managed vs. Unmanaged PinmemberErnst Kuschke21:21 10 Mar '04  
Generalbug report PinmemberTweety18:46 2 Mar '04  
GeneralRe: bug report PinmemberErnst Kuschke20:40 2 Mar '04  
GeneralFinalizers should almost never be written [modified] PinmemberFrank Hileman4:28 2 Mar '04  
GeneralRe: Finalizers should almost never be written PinmemberErnst Kuschke4:39 2 Mar '04  
GeneralRe: Finalizers should almost never be written Pinmemberkimjim20:37 14 Mar '06  
GeneralRe: Finalizers should almost never be written PinmemberFrank Hileman8:00 24 Apr '07  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 29 Feb 2004
Editor: Smitha Vijayan
Copyright 2004 by Ernst Kuschke
Everything else Copyright © CodeProject, 1999-2009
Web16 | Advertise on the Code Project