Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

wrapping MemoryStream in a using

Tags:

c#

.net

stream

I've been told that System.IO.MemoryStream need not be wrapped in a using block because there is no underlying resource, this kinda goes against what i've always been told about streams ("if in doubt, use a using").

Is this true? Why then does MSDN example use one (summarized below)?

using(MemoryStream memStream = new MemoryStream(100))
{
            // do stuff
}
like image 202
gingerbreadboy Avatar asked Jan 08 '10 16:01

gingerbreadboy


People also ask

What is the use of MemoryStream?

MemoryStream encapsulates data stored as an unsigned byte array that is initialized upon creation of a MemoryStream object, or the array can be created as empty. The encapsulated data is directly accessible in memory. Memory streams can reduce the need for temporary buffers and files in an application.

Do I need to close MemoryStream?

You needn't call either Close or Dispose . MemoryStream doesn't hold any unmanaged resources, so the only resource to be reclaimed is memory. The memory will be reclaimed during garbage collection with the rest of the MemoryStream object when your code no longer references the MemoryStream .

What is the difference between Stream and MemoryStream?

You would use the FileStream to read/write a file but a MemoryStream to read/write in-memory data, such as a byte array decoded from a string. You would not use a Stream in and of itself, but rather use it for polymorphism, i.e. passing it to methods that can accept any implementation of Stream as an argument.

How do you save on MemoryStream?

Save MemoryStream to a String StreamWriter sw = new StreamWriter(memoryStream); sw. WriteLine("Your string to Memoery"); This string is currently saved in the StreamWriters buffer. Flushing the stream will force the string whose backing store is memory (MemoryStream).


6 Answers

If the class implements IDisposable, it should be disposed.

You don't need to bother guessing whether it does anything of significance or not - that's for the class to decide and implement. If the class doesn't do anything when the object gets disposed, then there's really no cost anyway, so there's no harm.

Encapsulation is one of the cornerstones of object oriented development. Why go out of your way to break that, especially if there's no good reason?

like image 128
Michael Burr Avatar answered Oct 02 '22 23:10

Michael Burr


The C# idiom is that if an object implements IDisposable then you use a using block. This will allow all resources being used by the object be disposed of properly. You're not suppose to know the implementation details of MemoryStream. What you do know is that it implements IDisposable so you should dispose of it properly. Further, you think that you know now that it doesn't need to free any resources but how do you know that in the future MemoryStream won't change its underlying implementation so that it does use resources that need to be freed using Dispose? You don't, so since it implements IDispoable you have more future-proof code by just using the pattern now. Second, what if you change your code in the future to use a different type of Stream that does have managed resources? By wrapping the MemoryStream in a using block now you reduce maintenance issues in the future; again, this is the correct way to use objects, and specifically Streams that implement IDisposable. Third, it's a clear way to signal to readers that you are done using the object; it's what readers of your code will expect to see when they see you are using objects that implement IDisposable. Finally, this is the current implementation of MemoryStream.Dispose:

protected override void Dispose(bool disposing) {
    try {
        if (disposing) {
            this._isOpen = false;
            this._writable = false;
            this._expandable = false;
        }
     }
     finally {
         base.Dispose(disposing);
     }
}

So, this marks the stream as closed, not-writable and not-growable. If somehow someone else got a hold of a reference to the same MemoryStream, it now becomes unusable to them which could be a good thing. But this is really the least important issue; the implementation details don't matter.

Use a using block because MemoryStream implement IDispoable. Don't not use a using block because you think that MemoryStream doesn't have any resources that need to be freed.

like image 40
jason Avatar answered Oct 02 '22 23:10

jason


A guideline is that if it implements IDisposable then you should dispose of it. You're just working with an API and are not aware of the implementation so you've no reason to not put it in a using block.

like image 34
Charlie Avatar answered Oct 02 '22 21:10

Charlie


Having had a quick look in Reflector, it appears that Dispose on the MemoryStream does little other than to mark the stream as not being open, writeable or expandable.

Having said that, as a general approach, you should probably keep with the dispose pattern; escpecially as Streams all follow the "decorator" approach and should be easy to swap out for each other, or wrap one with another. Today's MemoryStream may get swapped out for another stream that does care tomorrow.

like image 33
Rob Levine Avatar answered Oct 02 '22 23:10

Rob Levine


You do not lose anything by wrapping the memory stream in a using block, so if there's doubt, just do it. :)

like image 38
Greg D Avatar answered Oct 02 '22 23:10

Greg D


As Charlie said, it is a recommended practice to Dispose of all objects of classes that implements IDisposable.

If you look into the implementation of MemoryStream.Dispose(bool) (which is called by Stream.Dispose()), it becomes obvious you should be disposing of it since it updates a few control flags:

protected override void Dispose(bool disposing)
{
    try
    {
        if (disposing)
        {
            this._isOpen = false;
            this._writable = false;
            this._expandable = false;
        }
    }
    finally
    {
        base.Dispose(disposing);
    }
}
like image 36
Alfred Myers Avatar answered Oct 02 '22 23:10

Alfred Myers