If an object you're using implements IDisposable, it's telling you it has something important to do when you're finished with it. That important thing may be to release unmanaged resources, or unhook from events so that it doesn't handle events after you think you're done with it, etc, etc. By not calling the Dispose, you're saying that you know better about how that object operates than the original author. In some tiny edge cases, this may actually be true, if you authored the IDisposable class yourself, or you know of a bug or performance problem related to calling Dispose. In general, it's very unlikely that ignoring a class requesting you to dispose it when you're done is a good idea.
Talking about finalizers - as has been pointed out, they have a cost, which can be avoided by Disposing the object (if it uses SuppressFinalize). Not just the cost of running the finalizer itself, and not just the cost of having to wait till that finalizer is done before the GC can collect the object. An object with a finalizer survives the collection in which it is identified as being unused and needing finalization. So it will be promoted (if it's not already in gen 2). This has several knock on effects:
- The next higher generation will be collected less frequently, so after the finalizer runs, you may be waiting a long time before the GC comes around to that generation and sweeps your object away. So it can take a lot longer to free memory.
- This adds unnecessary pressure to the collection the object is promoted to. If it's promoted from gen 0 to gen 1, then now gen 1 will fill up earlier than it needs to.
- This can lead to more frequent garbage collections at higher generations, which is another performance hit.
- If the object's finalizer isn't completed by the time the GC comes around to the higher generation, the object can be promoted again. Hence in a bad case you can cause an object to be promoted from gen 0 to gen 2 without good reason.
Obviously if you're only doing this on one object it's not likely to cost you anything noticeable. If you're doing it as general practice because you find calling Dispose on objects you're using tiresome, then it can lead to all of the problems above.
Dispose is like a lock on a front door. It's probably there for a reason, and if you're leaving the building, you should probably lock the door. If it wasn't a good idea to lock it, there wouldn't be a lock.
Dispose
allows you to release resources earlier, which is a good thing. A finalizer is for "last chance" resource deallocations. – Flannel.dispose()
anywhere in the first place instead of relying on finalizers. If you can't get theMyImage
you use todispose
theImage _img
, you are in the same reason as if you had anImage
and couldn'tdispose
it. – Rendezvousdispose
theImage
). Not doing this seems like not checking whethermalloc
returnedNULL
in C because "I won't consume that much memory". – Rendezvousmalloc
returnedNULL
in C". False. Image implements a finalizer which means eventually (possibly at the cost of performance) GC will cause it to clean itself up. – Knoutmalloc
may never returnNULL
. In both cases, you'll be fine most of the time but that's no reason to abandon good practice especially since it costs so little to at provide the solution even if you don't use them yourself respectively to at least detect the problem when it occurs. – Rendezvous