Could someone explain what might happen if you don\'t Dispose
some IDisposable
entity (by using
or direct Dispose
cal
Some objects will, during their existence, do things to outside entities that they are expected to clean up. There is a very strong convention that such objects should whenever practical implement IDisposable and perform any required cleanup when the IDisposable.Dispose() method is called. The system allows objects to request notification if it notices that they've been abandoned, but there's no guarantee that such notifications will happen in time to be useful. Further, unless one is careful, it's possible for such notifications to fire early and try to clean up things that are still in use.
Unless you know that a particular class of IDisposable object may be safely abandoned, don't. Always clean up after yourself whenever practical. "Finalization" (the process of notifying objects they've been abandoned) is dangerous and can create many Heisenbugs. Avoid relying on it if any practical alternative exists.
It completely depends on the object in question.
There are fourfive reasons that an object might implement IDisposable
:
It owns native resources.
If so, it should call Dispose
in its finalizer, so all that happens if you forget to dispose it is that the native resources last longer than necessary.
If you create lots of such objects at once and don't dispose them, you may run out of native resources.
It owns managed objects that are disposable.
The objects that it owns will fall also into one of these categories; see the relevant category.
It has a long-lasting reference to itself that won't be freed naturally (eg, it handles a static
event)
The dispose method would clear this reference (eg, unregister the event handler)
If so, not calling Dispose
will cause it to last forever.
It inherits a disposable base class, such as Stream
or Component
, but doesn't actually need to be disposed. (eg, MemoryStream
)
If so, not calling Dispose
is harmless, unless the class changes in the future.
It performs some action in its Dispose
method that people should call in a using
statement (eg, using (Html.BeginForm() { ... }
)
If so, not disposing the object will defeat its entire purpose, which is to do that action.
One distinction that is worth pointing out is that .NET manages memory, but not resources. IDisposable
is designed so that clients of classes implementing this interface can dispose resources deterministically.
Joe Duffy states the distinction pretty clearly in his post entitled DG Update: Dispose, Finalization, and Resource Management:
The CLR’s garbage collector (GC) does an amazing job at managing memory allocated directly to CLR objects, but was explicitly not designed to deal with unmanaged memory and OS-managed resources.
IDisposable is meant to wrap an unmanaged resources (i.e. not .NET memory). So if you don't dispose them, you will leak things like open database connections, Window handles, file handles, etc. depending on what type of IDisposable you're failing to dispose.
So it's not truly a memory leak, but it can lead to performance degradation and eventually a crash as you run out of the unmanaged resources.
Not calling .Dispose() could result in a memory leak. Otherwise, not calling Dispose() will simply result in delayed collection by the GC. Overall, the effects will completely depend on what objects are instantiated (see SLaks for a great bullet list). By implementing IDisposable
, you are taking responsibility for cleaning up your mess, so to speak.
What implementation should do is tell the GC (Garbage Collector) that it should suppress collection because you are going to take care of it. That way, when the Dispose() method is called on your IDisposable object, you should have taken care of clean up - i.e., calling Dispose() on objects within that class, clearing collections, etc.
And, FYI, the using{...}
clause can only be used on objects implementing IDisposable because at the closing bracket the Dispose() method is called automatically:
using (MyDisposableObject dispObj = new MyDisposableObject())
{
// use dispObj for some work
} // dispObj.Dispose() is automatically called here
Any number of things might happen because a class if free to implement Dispose
however they choose to.
What is usually disposed is not managed resources (which usually take care of themselves) but unmanaged ones such as database connections, file locks, etc.
Generally speaking Disposed is called in the finalizer when garbage collection gets around to it, however for instance if you write to a file and you don't close it (which Dispose does) then you're preventing anything other program (including other parts of your code in the same program) from opening that file (except possibly in read-only mode).
If you hold on to database connections for longer than necessary you could hit the max open connections and stop your app from using the database.
In generally if a class implements IDisposable
it's saying that I have something that needs to be disposed, and it should be disposed as soon as possible, not waiting for the garbage collector to come around.