1

Assume I have a string class with a method ToStream().

class FooBar
{
    pubic Stream ToStream( )
    {
        byte[ ] barFooBytes = Encoding.UTF8.GetBytes( this.BarFoo );
        return new MemoryStream( barFooBytes );
    }
}

Now assume I have a class getting this stream.

class BarFoo
{
    pubic void DoCrazyStuff( )
    {
        using( Stream fooBarStream = ( new FooBar( ) ).ToStream( ) )
        {
            // Doing some really crazy stuff!
        }
    }
}

Does it still make sense to use a using outside of the method creating the stream?

Hint: This is not an actual real life scenario. It's a pure technical question of interest. So this code is minified just to clarify the question.

codekandis
  • 712
  • 1
  • 11
  • 22
  • Why `new Foobar()` - why not make the `ToStream` method a static method if it doesn't need persistent instance state? – Dai Nov 28 '18 at 09:21
  • Assume I can create a `Action>`, does it make sense ? The only correct answer is: **It depends**. We need to know more details in order to give an educated guess. – Fabjan Nov 28 '18 at 09:21
  • Also, I recommend against returning a `Byte[]` as a `MemoryStream` if the data is natively a `Byte[]` unless you have a constraint or use-case elsewhere that requires it. If the data is primarily a `Byte[]` but some consumer needs it as a `Stream` then wrapping it in a `MemoryStream` should be the consumer's responsibility, not the producer's. – Dai Nov 28 '18 at 09:22
  • 1
    Can we not have swear words in questions please, thanks – Liam Nov 28 '18 at 09:23
  • @dai The question is not about the instanziation of `FooBar`. It's about the `using` on the stream as a return value. And this snippet just shows what I meant. @liam Where did I use swear words? – codekandis Nov 28 '18 at 09:26
  • @fabjan I just wanted to know if the using is working correctly in this case. – codekandis Nov 28 '18 at 09:28
  • @fabjan @codecaster Where this question is a duplicate of the asked one? These are two completely different setups of using streams and `using`. – codekandis Nov 28 '18 at 09:39

1 Answers1

5

With using/IDisposable, the important question to be able to answer at any time is "who owns this object?". In this instance, the ToStream method has to return a Stream, so whilst it owned the object whilst it was running, it and the class it's part of assume no further responsibility for it. It therefore doesn't Dispose or wrap it in a using.

Therefore, we can decide that ownership of the object has been passed back to the caller of the ToStream method. So, as the new owner of the object, it's your responsibility to wrap it in a using, manually Dispose of it or pass the ownership on to something else.


As John's answer and the comments below it point out, a MemoryStream, specifically, doesn't significantly benefit from Dispose being called on it (the buffer remains allocated). However, it implements Dispose because it inherits from Stream and contractually, all that your ToStream method promised to provide was a Stream, not a MemoryStream, so using/Dispose is correct for the caller.

Damien_The_Unbeliever
  • 234,701
  • 27
  • 340
  • 448
  • I hope that C# 9.0 adds something like Rust's ownership and borrowing semantics because that solves this problem entirely. – Dai Nov 28 '18 at 09:38