Nerdy tidbits from my life as a software engineer

Wednesday, May 20, 2009

Annoying Gotcha #230

Ack, is this annoying.  The following code will almost certainly cause problems for you if you’re not careful:

using (XmlReader reader = XmlReader.Create(File.Open(path, FileMode.Open)))
{
  ...
}

Why does this cause problems?  Because the default XmlReaderSettings passed into the Create overload does not have the CloseInput property set to true.  This means that the file handle is not disposed of at the end of the using block – and it means that some other program, later on, can very easily run into IOExceptions when it tries to open the same file and gets blocked because another program never closed a file handle.

Of course the way around this is easy:

XmlReaderSettings settings = new XmlReaderSettings();
settings.CloseInput = true;

using (XmlReader reader = XmlReader.Create(File.Open(path, FileMode.Open), settings))
{
   ...
}

But the amount of time I’ve wasted in the last few days figuring out what’s going on before I was reminded that this is not the default behavior is rather depressing.  Why this isn’t the default setting, I can only guess.  I expect that when a stream is disposed, every stream that it decorates is also disposed.  Hence, passing in an XmlSettings object shouldn’t be necessary.  reader.Dispose() implies that the stream passed into the reader is also disposed.

But maybe what aggravates me the most is inconsistent behavior.  Most streams close their inner streams when they are disposed.  So why should XmlReader be any different?

3 comments:

Anonymous said...

What's wrong with:

XmlReader.Create(path)

Michael J. Braude said...

I don't think that method overload changes the default XML reader settings either, but I could be wrong.

Anonymous said...

"...but I could be wrong"

You are (check with Reflector). Since the XmlReader creates the stream, it must be responsible for closing it.