IDisposable and Finalization

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

I believe that I fully understand the concepts behind IDisposable and
finalization (at least I hope I do) and I would like to get feedback from the
experts so that I can forward them on to others.

There are people who think that if a class implements IDisposable then it
should include a finalizer. What I told them was that you should only
include a finalizer if you have unmanaged resources you need to ensure are
cleaned up. Otherwise you should not include a finalizer whether or not you
implement IDisposable.

As an example of this case, the one where you might want to implement
IDisposable but do not need a finalizer, I said assume you have a class that
internally makes use of a FileStream object. It might open the object up at
some point during its lifetime and keep it open from then on. In this case
you might want to implement IDisposable to provide an explicit mechanism for
the caller to indicate they are done with your class. The implementation in
your class would simply call the FileStream's IDisposable.Dispose() method.

I argue that this class does not need a finalizer and in fact if this class
did include a finalizer it would be of no use. By the time the finalizer was
called you could not do anything with your FileStream instance as it may have
already been disposed (assuming you don't expose the instance outside your
class).

Is my statement/explanations valid?
 
Some thoughts...

nickdu said:
I believe that I fully understand the concepts behind IDisposable and
finalization (at least I hope I do) and I would like to get feedback from
the
experts so that I can forward them on to others.

There are people who think that if a class implements IDisposable then it
should include a finalizer.

I think it is the other way around more rightly - classes that have a
finalizer implement IDisposable.
and the Dispose method supresses the finalization after cleaning up the
resources.
What I told them was that you should only
include a finalizer if you have unmanaged resources you need to ensure are
cleaned up.
Right.

Otherwise you should not include a finalizer whether or not you
implement IDisposable.
As an example of this case, the one where you might want to implement
IDisposable but do not need a finalizer, I said assume you have a class e
that
internally makes use of a FileStream object. It might open the object up
at
some point during its lifetime and keep it open from then on. In this
case
you might want to implement IDisposable to provide an explicit mechanism
for
the caller to indicate they are done with your class. The implementation
in
your class would simply call the FileStream's IDisposable.Dispose()
method.

I argue that this class does not need a finalizer and in fact if this
class
did include a finalizer it would be of no use. By the time the finalizer
was
called you could not do anything with your FileStream instance as it may
have
already been disposed (assuming you don't expose the instance outside your
class).

A better explanation can be justified taking the example of the BinaryWriter
class. The reason BinaryWriter class does
not have a finalizer is that it has a reference to the filestream object and
there can be no guarantee of the order
the objects are finalized. If the filestream object is finalized first, the
binarywriter would not have the stream to flush the remaining bytes
in the buffer whenever it would be finalized itself.

Hence, the BinaryWriter demands deterministic release of resource through
dispose pattern.

Other than these dependencies cases, the only other place where Dispose
exists, but no finalizer is the Component (System.ComponentModel) class.
This is more because the object lifetimes should be controlled by its
Container.
 
nickdu said:
I believe that I fully understand the concepts behind IDisposable and
finalization (at least I hope I do) and I would like to get feedback from the
experts so that I can forward them on to others.

There are people who think that if a class implements IDisposable then it
should include a finalizer. What I told them was that you should only
include a finalizer if you have unmanaged resources you need to ensure are
cleaned up. Otherwise you should not include a finalizer whether or not you
implement IDisposable.

Yes. You are correct. But, to word it with a little less ambiguity
you could say that you only need a finalizer if the class *directly*
holds unmanaged resources.

This seems to cause a lot of confusion among junior programmers who
have, for whatever reason, been told to always provide an
implementation for the Finalize method when implementing the
IDisposable interface.
As an example of this case, the one where you might want to implement
IDisposable but do not need a finalizer, I said assume you have a class that
internally makes use of a FileStream object. It might open the object up at
some point during its lifetime and keep it open from then on. In this case
you might want to implement IDisposable to provide an explicit mechanism for
the caller to indicate they are done with your class. The implementation in
your class would simply call the FileStream's IDisposable.Dispose() method.

Yes. That is correct.
I argue that this class does not need a finalizer and in fact if this class
did include a finalizer it would be of no use. By the time the finalizer was
called you could not do anything with your FileStream instance as it may have
already been disposed (assuming you don't expose the instance outside your
class).

Again, you are correct. But, to expand a bit, not only is it of no
use, it would only degrade the performance of the GC since the object
would be placed in the finalization queue. I believe the object would
be promoted unnecessarily to generation 1 of the heap as well.
Is my statement/explanations valid?

Yes, it appears that you have a good understanding of the concepts.
 
You wrote:

"The reason BinaryWriter class does not have a finalizer is that it has a
reference to the filestream object and there can be no guarantee of the
order the objects are finalized."

Is this the case? I would think:

The reason why the BinaryWriter does not have a finalizer is because it
doesn't need one. It does not *directly* (as Brian suggests) hold onto any
unmanaged resources. It has nothing to do with the order, or lack there of,
the objects are finalized.

Are you suggesting that if the order of finalization was deterministic, and
in this case the FileStream being finalized after the BinaryWriter, that the
BinaryWriter should contain a finalizer so that it could call Flush()?

You also stated:

"Other than these dependencies cases, the only other place where Dispose
exists, but no finalizer is the Component (System.ComponentModel) class.
This is more because the object lifetimes should be controlled by its
Container."

This makes it sound like the typical case is having a finalizer when
implementing IDisposable. I would think the opposite is true. I would think
the more common case are classes that need to implement IDisposable (to
provide explicit cleanup) but which do not directly hold onto unmanaged
resources and thus don't require a finalizer.
 
You are basically correct, but it is far more complex then this. There are
three possible combinations...

1. Finalizer
2. Dispose
3. Finalizer and Dispose

and other combinations involve objects that contain references to

1. unmanaged resources
2. managed objects that implement IDisposable or have other cleanup
semantics
3. both


This link does a pretty good job of covering most of the issues of these
different cases...
http://www.bluebytesoftware.com/blog/PermaLink.aspx?guid=88e62cdf-5919-4ac7-bc33-20c06ae539ae

and this follows up on it...
http://www.bluebytesoftware.com/blog/PermaLink.aspx?guid=0b1d6b09-e240-42d4-85fb-d9002cdc8f5a

a thought about using the finalizer as a debugging aid...
I prefer to regard the presence of an IDisposable interface as a contract
that must be honored, and the failure to call Dispose is treated
as a bug. For that reason, in debug builds (or early in the development
cycle) I include a finalizer in classes that implement IDisposable - if the
finalizer ever runs it means that some other class did not call the Dispose
method. If it is not obvious what the problem is I capture the context of
how the object got created so I can determine which object should have
invoked the Dispose method. The performance impact of fnalizers is real but
unless there are lots and lots of objects with finalizers I don't think it
is likely to cause a significant impact. Code that works correctly, and that
contains diagnostics to report on when it does not behave correctly, is
often more important then code that squeezes every last bit of performance
from the system.

Dave
 
Actually I think you're complicating it more than it needs to be. I don't
care if I'm referencing objects that hold onto unmanaged resources or not.
If I don't hold onto an unmanaged resource myself then I don't need to supply
a finalizer. At least that's the way I understand it. If I contain objects
that implement IDisposable I should probably implement IDisposable so that I
can expose the explicit cleanup of those resources by funnelling down the
call.
--
Thanks,
Nick


David Levine said:
You are basically correct, but it is far more complex then this. There are
three possible combinations...

1. Finalizer
2. Dispose
3. Finalizer and Dispose

and other combinations involve objects that contain references to

1. unmanaged resources
2. managed objects that implement IDisposable or have other cleanup
semantics
3. both


This link does a pretty good job of covering most of the issues of these
different cases...
http://www.bluebytesoftware.com/blog/PermaLink.aspx?guid=88e62cdf-5919-4ac7-bc33-20c06ae539ae

and this follows up on it...
http://www.bluebytesoftware.com/blog/PermaLink.aspx?guid=0b1d6b09-e240-42d4-85fb-d9002cdc8f5a

a thought about using the finalizer as a debugging aid...
I prefer to regard the presence of an IDisposable interface as a contract
that must be honored, and the failure to call Dispose is treated
as a bug. For that reason, in debug builds (or early in the development
cycle) I include a finalizer in classes that implement IDisposable - if the
finalizer ever runs it means that some other class did not call the Dispose
method. If it is not obvious what the problem is I capture the context of
how the object got created so I can determine which object should have
invoked the Dispose method. The performance impact of fnalizers is real but
unless there are lots and lots of objects with finalizers I don't think it
is likely to cause a significant impact. Code that works correctly, and that
contains diagnostics to report on when it does not behave correctly, is
often more important then code that squeezes every last bit of performance
from the system.

Dave
 
You are trying to reduce a complex set of interactions and concerns to a
simple rule. For simple cases you are correct, but there are cases that are
more complex.

nickdu said:
Actually I think you're complicating it more than it needs to be. I don't
care if I'm referencing objects that hold onto unmanaged resources or not.
If I don't hold onto an unmanaged resource myself then I don't need to
supply
a finalizer. At least that's the way I understand it. If I contain
objects
that implement IDisposable I should probably implement IDisposable so that
I
can expose the explicit cleanup of those resources by funnelling down the
call.
 
Back
Top