Search code examples
c#.net-2.0

Icon still usable after calling Dispose()?


I've been trying to sort out some of our code using Dispose properly in a number of places that things were being left hanging around. Once such instance was Icons, and something I noticed which I thought was odd, if I call Icon.Dispose() I was still able to use the Icon.

So I extracted it out into a little console application that I fully expected to crash (throw an ObjectDisposedException), but it didn't... Am I mis-understanding what dispose should be doing here?

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.IO;

namespace DisposeTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Icon icon = new Icon(@"C:\temp\test.ico");
            icon.ToBitmap().Save(@"C:\temp\1.bmp");
            icon.Save(new FileStream(@"C:\temp\1.ico", FileMode.OpenOrCreate, FileAccess.ReadWrite));
            icon.Dispose();
            GC.Collect(); // Probably not needed, but just checking.
            icon.Save(new FileStream(@"C:\temp\2.ico", FileMode.OpenOrCreate, FileAccess.ReadWrite));
            icon.ToBitmap().Save(@"C:\temp\2.bmp");
        }
    }
}

Solution

  • It doesn't crash because the Dispose() method doesn't do anything in your case. The Icon class wrapper can wrap two distinct sources of icon data. In your case, the icon data comes from a file and is stored in a byte[]. Which is not a system resource that requires disposing, the garbage collector already takes care of it.

    The other icon data source is from a Windows handle. Fairly rare, but you'll get that when using Icon.FromHandle() or one of the System.Drawing.SystemIcons. Now it does wrap an unmanaged resource that makes using Dispose() useful.

    This pattern is not unusual. There are also plenty of cases where Dispose() is inherited into a class where it doesn't make much sense. Like MemoryStream or BackgroundWorker. The conventional wisdom is to dispose them anyway.