Garbage Collection for List Objects

user1897659 picture user1897659 · Dec 21, 2012 · Viewed 7.1k times · Source

I would like to ask what is the efficiency way the clean and dispose the object collected in the List (Of Object)?

Is that by calling the List.Clear() method will automatic clean all the object collected by it?

For Example consider the below example

public partial class Form1 : Form
{
    FontCollection m_fontCollection;

    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        m_fontCollection = new FontCollection();
        for (int i = 0; i < 5000; i++)
        {
            Font font = new Font("Arial", 23);

            FontImpl impl = new FontImpl(font, Color.Black);
            impl.AfterChange += 
                new FontImpl.AfterChangeHandler(impl_AfterChange);

            m_fontCollection.Add(impl);
        }

        m_fontCollection.Dispose();
        MessageBox.Show("TakeSnap");
    }

    void impl_AfterChange()
    {
        throw new NotImplementedException();
    }
}

public class FontCollection : IEnumerable, IDisposable
{
    IList<FontImpl> m_Implementation = new List<FontImpl>();

    internal void Add(FontImpl impl)
    {
        this.m_Implementation.Add(impl);
    }

    public IEnumerator GetEnumerator()
    {
        return this.m_Implementation.GetEnumerator();
    }

    public void Dispose()
    {
        m_Implementation.Clear();
        m_Implementation = null;
    }
}

public class FontImpl
{
    private Font m_Font;
    private Color m_color;

    public FontImpl(Font newFont, Color newColcor)
    {
        m_Font = newFont;
        m_color = newColcor;
    }

    public event AfterChangeHandler AfterChange;

    public delegate void AfterChangeHandler();
}

When i run the above application ANTS memory profiler i could see the memory leaks Font and FontFamily (I could not able to upload the screen) and how to remove these leaks

Answer

Jonathon Reinhart picture Jonathon Reinhart · Dec 21, 2012

In general, you shouldn't need to worry about garbage collection, and when it occurs. An object is eligible for GC when there are zero references to it.

The thing you should pay attention to, however, are IDisposable objects. When you are finished with an IDisposable object, you really need to be calling Dispose() on it. If the object lives within the local scope of a functinon, then a using block makes this easy:

using (var resource = new SomeIDisposable()) {
    // use resource

    // resource.Dispose() is automatically called, *even if* an exception
    // is thrown.
}

You can cause memory leaks by ending up with "dangling references" to objects, which prevent them from being garbage collected. Most often the cause of this is with event handlers. When you subscribe to an event exposed by object A, with an event handler on object B, A gets a reference to B:

class B {
    void hook_up_to(A a) {
        a.SomeEvent += Handler;     // `a` gets a reference to `this`
    }

    void Handler(object sender, EventArgs e) {
    }
}

class Program {
    private A _a = new A();

    static void SomeMethod() {
        var b = new B();

        b.hook_up_to(_a);    // _a now has a reference to b

        // b goes out of scope.
    }
}

Normally, when b goes out of scope, the object it references would be eligible for garbage collection. In this case though, b hooked up to an event published by member variable _a, which caused _a to gain a reference to b. Now there is one outstanding reference to b, which is impossible1 to clear, and b is ineligible for GC. This is a memory leak.

1 The only way reference to b in this case is this pointer if/when the event handler is fired.