You seem to be confusing two distinct but related topics:
1) Implementing IDisposable so that classes which use other objects as
part of their implementation, which themselves need disposing, can be
disposed of, in a recursive manner.
2) Implementing .NET finalizers, for freeing unmanaged resources, which
also involves implementing IDisposable.
1. To avoid possible memory leaks,
The IDisposable pattern is for resource leaks, typically not memory
leaks.
when you use this pattern, after you
have dealth with the unmanaged resources and before you take your
object off the finalize queue
Now you are talking about finalization - which is something different
from simply implementing IDisposable. Many objects implement IDisposable
to permit closing of files etc. - i.e. deterministic deallocation of
resources used by the class.
That is something *different* from Finalize() (aka ~MyClassName()),
which is for unmanaged resources *directly* represented by the managed
class.
You should only need to implement a finalizer (i.e. ~MyClassname()) when
you are wrapping an OS resource.
how are you sure that your managed
object resources are completely freed up of resources it's might be
using?
I don't understand this question, sorry.
2. I have the example in msdn that instanciates a Component object but
doesn't actually do anything with it, what is this class for?
What example, where? I presume it is a *placeholder* for something which
implements IDisposable (Component itself implements IDisposable), such
as a Stream or other resource.
public classA : IDisposable
{
private Component component = new Component(); //WHAT IS THIS
FOR????
I presume it is a placeholder.
private XmlTextReader reader;
private bool disposed = false;
This protects the class from being disposed multiple times. This is to
permit calling Dispose() multiple times - this is not an error.
public LoadFile(string FilePath)
{
reader = new XmlTextReader(FilePath);
}
public void CloseFile()
{
reader.Close();
}
I don't understand this code, this will throw an exception if LoadFile()
was never called.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
This class does not implement a finalizer (i.e. there is no ~classA()
method), so it does not need to call GC.SupressFinalize().
}
public void Dispose(bool disposing)
The overloaded Dispose which takes a bool argument should be made
virtual and protected. The reason behind this pattern is to centralize
logic for classes that need finalizers (which this class doesn't,
because it only contains other managed resources).
The idea behind this pattern is based on classes that implement a
finalizer, and that thus there are two ways that the Dispose method can
get called:
1) Explicitly via IDisposable.Dispose().
2) From the finalizer of this class.
When the method is called via IDisposable.Dispose(), then it needs to
dispose objects it references, as well as its own unmanaged resources.
When the method is called via the finalizer, it shouldn't access objects
it references, since they are dead objects - finalization only occurs
for objects no longer reachable from the main application object graph.
That's why the implementation of this method has the pattern:
---8<---
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// dispose referenced, managed resources
}
// dispose unmanaged, native OS resources
}
--->8---
For future proofness, this pattern is sometimes also used for classes
which don't have a finalizer. The reason this is done is that the class
may have descendants which also need some disposal logic. The idea is
that the descendants can override this protected Dispose method and
perform their disposal of managed resources, before calling the base
class's Dispose(bool). Then, the base class can implement IDispose, so
the subclasses don't (and shouldn't) need to.
Basically, with respect to IDisposable, there are three kinds of
classes:
1) Classes which don't need disposing.
2) Classes which use (i.e. have "ownership" semantics on a private
reference to) objects which need disposing, and therefore need disposing
themselves.
3) Classes which need finalizers, and therefore need disposing for
deterministic cleanup. These classes deal with unmanaged resources, and
thus are extremely rare.
Objects in category 1 don't need to implement IDisposable.
Objects in category 2 and 3 do need to implement IDisposable.
For objects in category 2, the dispose pattern is for future-proofness
and to permit descendants to be disposed when the IDisposable.Dispose()
method is called via the base class.
For objects in category 3, the dispose pattern is to centralize cleanup
depending on whether the cleanup was invoked via the finalizer, or
directly via the IDisposable.Dispose() method.
Objects in category 3 are very rare: you are unlikely to be implementing
them unless you are wrapping unmanaged resources, e.g. shared
memory-mapped files or direct hardware access.
{
if (!this.disposed)
{
if (disposing)
{
CloseFile();
//are there anything else you need to free up
here?????
}
}
this.disposed = true;
You don't need to flag the object as disposed if you are simply using
this in the "recursive IDisposable" scenario: i.e. if this class is
implementing IDisposable simply to propagate Dispose() calls to the
inner XmlTextReader, then the flag is not needed. It is safe to call
Dispose() multiple times on the inner XmlTextReader (it's always safe to
call Dispose() multiple times).
}
ClassA()
{
Dispose(false);
}
This is calling Dispose in the constructor? Or is this meant to be a
finalizer?
-- Barry