using() and dispose with multiple wrapped streams
Question
Am I right that you'd only need a using() for the outermost stream if you're doing e.g
MemoryStream mstr = new MemoryStream();
using(StreamWriter w = new StreamWriter(mstr)) {
....
}
As disposing the StreamWriter should also dispose/close the underlying stream, there's no need to do this ?:
using(MemoryStream mstr = new MemoryStream())
using(StreamWriter w = new StreamWriter(mstr)) {
....
}
(Note these are just examples, for how to dispose wrapped streams, not looking for alternatives like just use a StringWriter etc.)
Solution
My rule of thumb: If it implements IDisposable, dispose of it.
While currently (and probably forever), calling StreamWriter.Dispose() closes the underlying stream, other stream-derived classes you may use in the future may not. Also, it seems not to actually call Dispose() either, so non-MemoryStreams may not get properly disposed (although I can't think of any that would suffer from that right now).
So, while you can safely dispose only of the StreamWriter, I find it a much better practice to always use using blocks for disposables whenever possible.
OTHER TIPS
It's a good idea to put all dependent resources in their own using
blocks from a readability and maintainability point of view as much as anything. e.g. in the below code, after the final brace, it's impossible to attempt to access mstr
because it is scoped to within the block where it is valid:
using (MemoryStream mstr = new MemoryStream())
using (StreamWriter w = new StreamWriter(mstr) {
....
}
// cannot attempt to access mstr here
If you don't scope it like this, then it's still possible to access mstr
outside the scope of where it is valid
MemoryStream mstr = new MemoryStream();
using (StreamWriter w = new StreamWriter(mstr) {
....
}
mstr.Write(...); // KABOOM! ObjectDisposedException occurs here!
So while it may not always be necessary (and in this case it isn't) it's a good idea as it both clarifies and enforces your intention as to its scope.
From looking at the StreamWriter.Dispose method in Reflector, it looks like the underlying streams get closed, but not disposed. I would put each stream in a "using" block in order to explicity dispose of them all.
To answer your actual question. TextWriter's Dispose method
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
It calls a protected Dispose and passes true to it. From TextWriter.Dispose Method (Boolean)
When the disposing parameter is true, this method releases all resources held by any managed objects that this TextWriter references. This method invokes the Dispose method of each referenced object.
However it is best practice to wrap everything that implements IDisposable in a using block, because we cannot guarantee that that the protected Dipose method will always be called with the true parameter.
It's really a better practice to just always use a using
block.
"Always", except for the one well-known case of WCF proxy classes, where a design flaw can sometimes cause their Dispose
methods to throw an exception, losing your original exception.