
Signature
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk
> But unless you explicitly call GC.Collect() (which is generally a bad
> idea) you won't achieve anything by calling Dispose.
That's not true. It might be the case that you have references to this
object from places which will remain in place for quite some time, E.G. in a
form or a static member. Sure this is a mistake but by having some kind of
cleanup on classes which hold onto a lot of memory you will at least allow
the GC to collect the data it no longer requires.
> free the object from memory, it's just meant to release unmanaged
> resources. It *might* set a few member variables to null so that in
> particularly rare cases (where the object itself is in gen1 but it has
> references to gen0 objects, for instance) memory will become available
> earlier - but that's unlikely.
If my class has a dictionary<string, object> which allows me to look up an
object from a cache by some ID I can easily hold onto
A: A big chunk of data in the form of strings ( a few million for example)
B: A whole load of referenced objects
Now if I have a form that holds a reference to my object for too long, or I
make the mistake of holding a reference in a static variable etc, then by
disposing the object I will
A: Allow this memory to be reclaimed
B: Identify the object as disposed, and when (maybe under rare
circumstances) the reference holding code tries to use the object an
exception will occur (if you implement it correctly) informing you of the
problem.
I think it's good practise in situations like this because it releases
memory earlier and in addition helps you to find a bug which you might not
otherwise notice. For example in my object persistence framework I use
IDisposable to ensure that my LoadedObjectCache Dictionary<> unloads all
cached objects when I have finished with my "object space". Why? Why not!
I get the memory back quicker, and if I try to use the object afterwards due
to some erroneous code where I still have a reference but really shouldn't
then I get an ObjectDisposedException. As my OPF was designed for the
compact framework I find it additionally beneficial.
Pete
Jon Skeet [C# MVP] - 10 Feb 2008 23:14 GMT
> > But unless you explicitly call GC.Collect() (which is generally a bad
> > idea) you won't achieve anything by calling Dispose.
[quoted text clipped - 4 lines]
> cleanup on classes which hold onto a lot of memory you will at least allow
> the GC to collect the data it no longer requires.
Calling Dispose() won't clear those references unless you explicitly
make it do so though. I can't remember ever seeing *that* particular
situation - where the class itself knew where it was used
inappropriately.
You can clear your own references, but I personally think that's a poor
use of IDisposable.
> > free the object from memory, it's just meant to release unmanaged
> > resources. It *might* set a few member variables to null so that in
[quoted text clipped - 15 lines]
> exception will occur (if you implement it correctly) informing you of the
> problem.
What exactly does your Dispose method do here? Just set the member
variable to null?
Unless there's a real *need* to implement IDisposable, I don't like
putting the burden on callers.
> I think it's good practise in situations like this because it releases
> memory earlier and in addition helps you to find a bug which you might not
[quoted text clipped - 5 lines]
> then I get an ObjectDisposedException. As my OPF was designed for the
> compact framework I find it additionally beneficial.
Do you need to implement IDisposable for any direct/indirect unmanaged
resources? If not, the fact that you implement IDisposable solely in
case people misuse your object is going to make diligent callers do
extra work to call Dispose just in case you actually *do* do something
which is really required. In some cases that may mean implementing
IDisposable themselves, and may make other code harder to read.
I would rather work with the assumption that the data within my objects
is required while my objects themselves are required - and that when
they're not, those objects will become eligible for garbage collection,
along with whatever they reference (leaving aside shared references).
Garbage collection is designed around exactly that assumption - putting
in explicit releases is effectively saying it's not doing a good enough
job on its own.

Signature
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk