What tends to happen is if the item has purely managed resources, calling dispose is not necessarily required, but is strongly advised because it makes disposal deterministic. It isn't always required (in a technical sense) because those managed resources would likely themselves now be eligible for GC, or there is actually nothing to dispose by default and it's an extensibility point.
For unmanaged resources, the Dispose Pattern advises implementing a finalizer, which will be called on GC. If types do not implement the finalizer and dispose is not called, then it is possible (well, very likely) that resources would be left unhandled. Finalizers are the last chance offered by the runtime for clearing your stuff up - they are also time-limited.
Note, that it does not make GC or managed memory reclamation deterministic, disposal is not delete
from C++. A disposed item could be a long way away from actually being collected. However, in the managed world, you don't care about deterministic collection, only resource management - in other words, disposal.
That said, I always make sure I call Dispose or use a using
statement if a type is disposable, regardless of whether it uses managed or unmanaged resources - it is the expected convention:
public void Show()
{
using (var f = new Form1())
{
f.ShowDialog();
} // Disposal, even on exceptions or nested return statements, occurs here.
}
Update:
After a discussion with Servy I feel I have to express this point as the reasoning behind my advice of disposing where possible. In the case of MemoryStream
, it is clearly a disposable type, but actually does not dispose of anything currently.
Relying on this, however, is to rely on the implementation of MemoryStream
. Were this to change to include an unmanaged resource, this would then mean that a reliance on MemoryStream
not having anything to dispose becomes problematic.
Where possible (as is the case with IDisposable
) I prefer to rely on the public contract. Working against the contract in this instance would mean I am safe from underlying implementation changes.