97

Which one do I call?

Is it necessary to call both?

Will the other throw an exception if I have already called one of them?

ashwnacharya
  • 14,601
  • 23
  • 89
  • 112
  • Dispose() would handle everything – xandy Nov 25 '10 at 07:31
  • 4
    Wrap your usage in using and don't worry about it. using (var s = new MemoryStream()) { } See this question: http://stackoverflow.com/questions/11968289/memorystream-in-using-statement-do-i-need-to-call-close – Randy James Jul 15 '13 at 20:57
  • 1
    Call neither. The `Close()` [documentation](https://learn.microsoft.com/en-us/dotnet/api/system.io.stream.close?view=net-7.0#system-io-stream-close) says to make sure the stream is properly disposed instead of calling it, and the `MemoryStream` [documentation](https://learn.microsoft.com/en-us/dotnet/api/system.io.memorystream?view=net-7.0#remarks) clearly says that it is not necessary to call `Dispose()` as it doesn't have any resources to dispose. So, after you're done with a `MemoryStream`, just leave it like any other managed type and GC will do the rest. – saastn Apr 05 '23 at 18:11

10 Answers10

170

Close() and Dispose(), when called on a MemoryStream, only serve to do two things:

  • Mark the object disposed so that future accidental usage of the object will throw an exception.
  • Possibly1 release references to managed objects, which can make the GC's job a bit easier depending on the GC implementation. (On today's GC algorithms it makes no real difference, so this is a point for an academic discussion and has no significant real-world impact.)

MemoryStream does not have any unmanaged resources to dispose, so you don't technically have to dispose of it. The effect of not disposing a MemoryStream is roughly the same thing as dropping a reference to a byte[] -- the GC will clean both up the same way.

Which one do I call? Is it necessary to call both?

The Dispose() method of streams delegate directly to the Close() method2, so both do exactly the same thing.

Will the other throw an exception if I have already called one of them?

The documentation for IDisposable.Dispose() specifically states it is safe to call Dispose() multiple times, on any object3. (If that is not true for a particular class then that class implements the IDisposable interface in a way that violates its contract, and this would be a bug.)

All that to say: it really doesn't make a huge difference whether you dispose a MemoryStream or not. The only real reason it has Close/Dispose methods is because it inherits from Stream, which requires those methods as part of its contract to support streams that do have unmanaged resources (such as file or socket descriptors).


1 Mono's implementation does not release the byte[] reference. I don't know if the Microsoft implementation does.

2 "This method calls Close, which then calls Stream.Dispose(Boolean)."

3 "If an object's Dispose method is called more than once, the object must ignore all calls after the first one."

cdhowie
  • 158,093
  • 24
  • 286
  • 300
  • Note that the part about disposing the `MemoryStream` making the GC's job easier only applies if for some reason you held a reference to the disposed stream object. – Edward Brey Dec 22 '12 at 12:06
  • @EdwardBrey True. It depends on the GC implementation. All popular CLR implementations today use some variant of mark-and-sweep GC, so it's really an academic discussion -- today's GCs won't show any difference. – cdhowie Jul 15 '13 at 19:30
  • 5
    In reference to your footnote `1`, according to the [.NET Reference Source](http://referencesource.microsoft.com/) `.Dispose()` does not release the internal `byte[]` either. The only resource it sets `null` is `_lastReadTask` which is only used in the method `Task ReadAsync(byte[], int, int, CancellationToken)`. Besides setting that one variable null all it does is set `_isOpen`, `_writable`, and `_expandable` to `false`. – Scott Chamberlain Jan 29 '14 at 17:33
32

None of the above. 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.

If you have a long-lived reference to the MemoryStream, you can set that reference to null to allow the MemoryStream to be garbage collected. Close and Dispose free neither the steam buffer nor the MemoryStream object proper.

Since neither Stream nor MemoryStream have a finalizer, there is no need to call Close or Dispose to cause GC.SuppressFinalize to be called to optimize garbage collection. There is no finalizer to suppress.

The docs for MemoryStream put it this way:

This type implements the IDisposable interface, but does not actually have any resources to dispose. This means that disposing it by directly calling Dispose() or by using a language construct such as using (in C#) or Using (in Visual Basic) is not necessary.

Edward Brey
  • 40,302
  • 20
  • 199
  • 253
10

You can use the using block for this. It will automatically call Dispose when it goes outside of its scope.

Example:

using (MemoryStream ms = new MemoryStream())
{
    // Do something with ms..
}
// ms is disposed here

Hope this helped.

Kevin
  • 5,626
  • 3
  • 28
  • 41
8

Use using block so that your object is disposed if its implements IDisposable interface

Irvin Dominin
  • 30,819
  • 9
  • 77
  • 111
TalentTuner
  • 17,262
  • 5
  • 38
  • 63
6

the following code is Stream.Dispose from reflector as you can see, you don't need to close if you dispose (which is implicit when using using)

public void Dispose()
{
    this.Close();
}
vc 74
  • 37,131
  • 7
  • 73
  • 89
6

Which one do I call?

Any of them.

Is it necessary to call both?

No, either one is sufficient.

Will the other throw an exception if I have already called one of them?

No, disposable pattern declares that subsequent calls to Dispose don't cause negative effects.

KthProg
  • 2,050
  • 1
  • 24
  • 32
QrystaL
  • 4,886
  • 2
  • 24
  • 28
  • Just went through this on a live application. Close and Dispose do act differently in CLR 4.5. Dispose should be sufficient, but you can call Close and then Dispose if you wish. – rkralston Jan 23 '17 at 16:05
4

Calling Close() will internally call Dispose() to release the resources.

See this link for more information: msdn

Hps
  • 1,177
  • 8
  • 9
2

In .NET 3.5 (haven't checked other versions), methods are called in the following order when disposing a MemoryStream:

  1. Stream.Dispose()
    • simply calls Close
  2. Stream.Close()
    • calls Dispose(true), then GC.SuppressFinalize(this)
  3. MemoryStream.Dispose(true)
    • sets _isOpen , _writable, and _expandable flags to false
  4. Stream.Dispose(true)
    • closes async event if active
Tor Langlo
  • 191
  • 2
  • 6
2

Calling only Dispose() will do the trick =)

abatishchev
  • 98,240
  • 88
  • 296
  • 433
Singleton
  • 3,701
  • 3
  • 24
  • 37
1

As a first solution, it's recommended to use using statements wherever possible. This is described here: http://msdn.microsoft.com/en-us/library/yh598w02.aspx

When the lifetime of an IDisposable object is limited to a single method, you should declare and instantiate it in the using statement. The using statement calls the Dispose method on the object in the correct way, and (when you use it as shown earlier) it also causes the object itself to go out of scope as soon as Dispose is called. Within the using block, the object is read-only and cannot be modified or reassigned.

Coming to the question now, as others suggested in most .NET framework classes, there is no difference between Close() and Dispose() and it doesn't matter which of the two methods you call. You should call one but not both. However, there are exceptions.

There are exceptions; for example, System.Windows.Forms.Form and System.Data.SqlClient.SqlConnection have different behavior for Close() and Dispose().

For complete details, you can check here: https://blogs.msdn.microsoft.com/kimhamil/2008/03/15/the-often-non-difference-between-close-and-dispose/

sin2akshay
  • 333
  • 1
  • 2
  • 11