6

Quick question about using nested disposables in a single 'using' statement: Should I write out each disposable's using statement, or can I nest them into one? Example:

using( FileStream inFile = new FileStream( "myFile.txt", FileMode.Open ) )
using( GZipStream gzip = new GZipStream( inFile, CompressionMode.Decompress ) )
using( FileStream outFile = new FileStream( "myNewFile.txt", FileMode.CreateNew ) )
{
    gzip.CopyTo( outstream );
}

vs.

using( GZipStream gzip = new GZipStream( new FileStream( "myFile.txt", FileMode.Open ), CompressionMode.Decompress ) )
using( FileStream outFile = new FileStream( "myNewFile.txt", FileMode.CreateNew ) )
{
    gzip.CopyTo( outstream );
}

Just curious if when the block is done executing, the unnamed FileStream from "myFile.txt" gets cleaned up because it's in the using statement with the GZipStream or if it stays open and needs to be cleaned up sometime after that.

Edit: Just to be clear, I'm not asking about nesting using statements. I'm asking whether or not an IDisposable that is created inside another IDisposable's 'using' statement will be disposed of at the end of the block. Any explanation on why or why not would be appreciated.

Meloviz
  • 571
  • 6
  • 16
  • Possible duplicate of [Nested using statements in C#](http://stackoverflow.com/questions/1329739/nested-using-statements-in-c-sharp) – Joshua Jan 07 '16 at 20:25
  • 3
    If the FileStream constructor succeeds but the GZipStream constructor fails then, well, oops. – Hans Passant Jan 07 '16 at 20:28
  • 1
    Perhaps worth setting up a very simple set of dummy classes that implement IDisposable and watch what happens in the debugger? – DanS Jan 07 '16 at 20:28
  • 1
    Nothing in the second example is *explicitly* disposing of the first `FileStream` object. It *might* get disposed by the `GZipStream` object when *that* object is disposed, but it seems more more reasonable to explicitly dispose of it yourself such as in the first example. – David Jan 07 '16 at 20:33
  • 3
    Note that Dispose is idempotent if implemented correctly. It should never be wrong to accidentally "double-dispose" an object. So I would likely err on the side of more disposals, not fewer. – Eric Lippert Jan 07 '16 at 20:39

3 Answers3

6

It depends on the constructor, GZipStream disposes of the stream you passed in when you dispose of it unless you use one of the overloads that takes in a bool and you pass in true to leaveOpen.

However you do run a risk doing this. If GZipStream throws a ArgumentException because the CanRead property of the stream is false the passed in stream does not get disposed of.

Personally I rather not depend on "something not going wrong" and instead usually code defensively and use the 3 statement version.


Edit: Just to be clear, I'm not asking about nesting using statements. I'm asking whether or not an IDisposable that is created inside another IDisposable's 'using' statement will be disposed of at the end of the block. Any explanation on why or why not would be appreciated.

If that is your question then the answer is: No, only the object declared that was assigned to (using var whatever = ...) will be disposed, any other objects created are dependent on the code of whatever the "outer" object is to be implemented to "chain call" the Dispose() methods.

Scott Chamberlain
  • 124,994
  • 33
  • 282
  • 431
3

if when the block is done executing, the unnamed FileStream from "myFile.txt" gets cleaned up because it's in the using statement with the GZipStream

Even when both constructors succeed, it still depends on the design of the 'owning' class. A StreamReader will close its BaseStream but many other classes won't.

You don't want your code to depend on such murky and liable to change details.

H H
  • 263,252
  • 30
  • 330
  • 514
2

Simple answer is no - you need to wrap every object.

Nigrimmist
  • 10,289
  • 4
  • 52
  • 53