CHAPTER 13 UNDERSTANDING OBJECT LIFETIME
// Assume you have imported
// the System.IO namespace...
static void DisposeFileStream()
{
FileStream fs = new FileStream("myFile.txt", FileMode.OpenOrCreate);
}
// Confusing, to say the least!
// These method calls do the same thing!
fs.Close();
fs.Dispose();
While it does feel more natural to “close” a file rather than “dispose” of one, this doubling up of
cleanup methods can be confusing. For the few types that do provide an alias, just remember that if a
type implements IDisposable, calling Dispose() is always a safe course of action.
Reusing the C# using Keyword
When you are handling a managed object that implements IDisposable, it is quite common to make use
of structured exception-handling to ensure the type’s Dispose() method is called in the event of a
runtime exception, like so:
static void Main(string[] args)
{
Console.WriteLine("***** Fun with Dispose *****\n");
MyResourceWrapper rw = new MyResourceWrapper ();
try
{
// Use the members of rw.
}
finally
{
// Always call Dispose(), error or not.
rw.Dispose();
}
}
While this is a fine example of defensive programming, the truth of the matter is that few developers
are thrilled by the prospects of wrapping each and every disposable type within a try/finally block just
to ensure the Dispose() method is called. To achieve the same result in a much less obtrusive manner,
C# supports a special bit of syntax that looks like this:
static void Main(string[] args)
{
Console.WriteLine("***** Fun with Dispose *****\n");
// Dispose() is called automatically when the
// using scope exits.
using(MyResourceWrapper rw = new MyResourceWrapper())
{
// Use rw object.
}
}
491