Thursday, 19 May 2011

C# Dispose Pattern

Here is an example of how to correctly implement the C# Dispose pattern, ensuring all your unmanaged resources are efficiently cleared from memory.

using System;
using System.IO;
using System.Xml;
using System.Xml.Linq;

internal class HowToImplementTheDisposePattern
{
private static void Main()
{
const string filename = "data.xml";

if (!File.Exists(filename))
CreateXmlFile(filename);

// the using statement implicitally calls the dispose on exit
using (var myDisposableObject = new MyDisposableClass(filename))
{
//do some work here with your object
}
}

public class MyDisposableClass : IDisposable
{
private XmlTextReader reader;
private bool disposed = false; // to detect redundant calls

public MyDisposableClass(string filename)
{
reader = new XmlTextReader(filename);
}

#region IDisposable Members

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

#endregion

protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
if (reader != null)
{
((IDisposable)reader).Dispose();
}
}

disposed = true;
}
}

~MyDisposableClass()
{
Dispose(false);
}
}

private static void CreateXmlFile(string filename)
{
var xml = new XDocument(
new XComment("This is a comment"),
new XElement("Root",
new XElement("Child1", "data1"),
new XElement("Child2", "data2"),
new XElement("Child3", "data3"),
new XElement("Child2", "data4"),
new XElement("Info5", "info5"),
new XElement("Info6", "info6"),
new XElement("Info7", "info7"),
new XElement("Info8", "info8")
));

xml.Save(filename);
}
}

1 comment:

  1. Shouldn't you also set reader = null after calling reader.Dispose()? Otherwise you are still holding a reference to the XmlTextReader object and it won't be garbage collected until after the instance of MyDisposableClass goes out of scope.

    I'm also curious why the (IDisposable) cast is used in so many of these examples?

    ReplyDelete