Dispose pattern

T

Thore Berntsen

I'm trying to understand the IDisposable pattern. In the sample on MSDN they
have added a destructor/finalizer like this:

~MyResource()
{
Dispose(false);
}

Calling Dispose(false) will only dispose non managed resources. If I
implement IDisposable only to dispose managed resources isn't this finalizer
unecessary then? Wouldn't the finalizer just at an extra burdon on the GC?

The MSDN sample is found here:
http://msdn2.microsoft.com/en-us/library/system.idisposable.aspx

Thore Berntsen
 
J

Jesse Houwing

* Thore Berntsen wrote, On 28-5-2007 12:03:
I'm trying to understand the IDisposable pattern. In the sample on MSDN they
have added a destructor/finalizer like this:

~MyResource()
{
Dispose(false);
}

Calling Dispose(false) will only dispose non managed resources. If I
implement IDisposable only to dispose managed resources isn't this finalizer
unecessary then? Wouldn't the finalizer just at an extra burdon on the GC?

The MSDN sample is found here:
http://msdn2.microsoft.com/en-us/library/system.idisposable.aspx

Thore Berntsen


That is correct. But it is best to implement your Dispose to call a
protected virtual Dispose(bool) method regardless of the fact whether
have a finalizer. Should you need one later you won't have to change much.

Jesse
 
L

Lee Alexander

Thore,

Your quite correct, there is certainly an added overhead using a finalizer,
so if you don't need it, don't use it,. Finalizable objects usually get
promoted to a higher generation and as a result stay in memory longer, as
the GC spends more of it's time in the lower generations. This is why
GC.SupressFinalize is so important, it stops the extra work being done if
the object has already been disposed. Also the finalizer is called in a
seperate thread so you have to take that into consideration if you have any
shared resources.

Regarding what Jesse said, I'm in the less code is better camp, so if you
don't use a finalizer I wouldn't bother with the Dispose( bool disposing )
method.


Regards

Lee Alexander
www.feedghost.com
An RSS Reader for Vista & XP
Synchronize, search, tag and share.
 
T

Thore Berntsen

Thank you both for confirming this. I wil remove my unecessary finalizers
rigth away. Actually I'm working on a Compact Framework application. Althoug
the GC is a bit different here I still think I should use the pattern from
the full framework.
 
J

Jon Skeet [C# MVP]

Jesse Houwing said:
That is correct. But it is best to implement your Dispose to call a
protected virtual Dispose(bool) method regardless of the fact whether
have a finalizer. Should you need one later you won't have to change much.

I disagree - I *very* rarely need a finalizer, which makes the whole
Dispose(bool) extra method a bit pointless. Why add an extra level of
indirection *just in case* you need it - you won't have to change much
anyway even without the extra level of indirection.

The only reason I can think of to add this complexity without an
immediate need is if you're creating a class which others may derive
from. At that point you're in a different ballgame, as changing things
later becomes a versioning issue.
 
J

Jon Skeet [C# MVP]

Lee Alexander said:
Your quite correct, there is certainly an added overhead using a finalizer,
so if you don't need it, don't use it,. Finalizable objects usually get
promoted to a higher generation and as a result stay in memory longer, as
the GC spends more of it's time in the lower generations. This is why
GC.SupressFinalize is so important, it stops the extra work being done if
the object has already been disposed. Also the finalizer is called in a
seperate thread so you have to take that into consideration if you have any
shared resources.

Note that even with SuppressFinalize there's an overhead in having a
finalizer to start with, in that the object is initially added to the
finalizer queue and then removed when SuppressFinalize is called. You'd
need to be creating an awful lot of objects to make this significant,
but it's still a hit.
 
J

Jesse Houwing

* Jon Skeet [C# MVP] wrote, On 28-5-2007 16:39:
I disagree - I *very* rarely need a finalizer, which makes the whole
Dispose(bool) extra method a bit pointless. Why add an extra level of
indirection *just in case* you need it - you won't have to change much
anyway even without the extra level of indirection.

The only reason I can think of to add this complexity without an
immediate need is if you're creating a class which others may derive
from. At that point you're in a different ballgame, as changing things
later becomes a versioning issue.

I'm usually building classes others need to derive from, or at least
make them so they can be inherited from in the near future. That's why I
usually do it from the start. It's also easier to understand for less
experienced programmers if you do it the same way under all circumstances..

Jesse
 
J

Jon Skeet [C# MVP]

Jesse Houwing said:
I'm usually building classes others need to derive from, or at least
make them so they can be inherited from in the near future.

I rarely try to design for inheritance - it's a very restrictive thing
to do, IME.
That's why I
usually do it from the start. It's also easier to understand for less
experienced programmers if you do it the same way under all circumstances..

And those less experienced programmers are likely to be *directly*
holding unmanaged resources (the only time you should usually have a
finalizer)? Scary.
 
J

Jesse Houwing

And those less experienced programmers are likely to be *directly*
holding unmanaged resources (the only time you should usually have a
finalizer)? Scary.

It is scary. The biggest problem is that they most of the time only
realize they are when they run Code Analysis. Which gives them a hint.
And it's usually during maintenance work after code ownership has
transferred to some other party.

Jesse
 
B

Ben Voigt

Jon Skeet said:
I disagree - I *very* rarely need a finalizer, which makes the whole
Dispose(bool) extra method a bit pointless. Why add an extra level of
indirection *just in case* you need it - you won't have to change much
anyway even without the extra level of indirection.

The only reason I can think of to add this complexity without an
immediate need is if you're creating a class which others may derive
from. At that point you're in a different ballgame, as changing things
later becomes a versioning issue.

Still a non-issue. The derived class needs a finalizer if it holds
unmanaged resources, and it is no more difficult for the programmer to
implement the finalizer than to override your Dispose(bool) class. The
finalizer should be first introduced by the class holding unmanaged
resources, not some base class.
 
B

Ben Voigt

Jon Skeet said:
Note that even with SuppressFinalize there's an overhead in having a
finalizer to start with, in that the object is initially added to the
finalizer queue and then removed when SuppressFinalize is called. You'd
need to be creating an awful lot of objects to make this significant,
but it's still a hit.

Not to mention that SupressFinalize will break derived objects that do need
a finalizer!
 
S

Samuel R. Neff

You can use the Finalizer to detect objects that are not properly
disposed.

Check out Sebastien Lorion's CSV reader [1]. He has code in there to
show when a disposable object is not disposed properly. Basically it
consists of adding this to your constructor:

_allocStack = new System.Diagnostics.StackTrace();

and this to your finalizer:

Debug.WriteLine("FinalizableObject was not disposed" +
_allocStack.ToString());

And instant failed-to-dispose detection with a stacktrace. Best to
put this code in conditional regions so it's only used in development.

Sam

[1] http://www.codeproject.com/cs/database/CsvReader.asp
 
J

Jon Skeet [C# MVP]

Samuel R. Neff said:
You can use the Finalizer to detect objects that are not properly
disposed.

And instant failed-to-dispose detection with a stacktrace. Best to
put this code in conditional regions so it's only used in development.

Exactly - I wouldn't want to burden a production system with extra
finalizers. On the other hand, I don't like having too much different
between debug and production :(
 
J

Jon Skeet [C# MVP]

Ben Voigt said:
Still a non-issue. The derived class needs a finalizer if it holds
unmanaged resources, and it is no more difficult for the programmer to
implement the finalizer than to override your Dispose(bool) class. The
finalizer should be first introduced by the class holding unmanaged
resources, not some base class.

I was more thinking of introducing Dispose(bool) early on - but even
that can be done at the level of the first class that requires it, I
guess, with a call to base.Dispose() only when disposing is true.
 
C

Christof Nordiek

Jon Skeet said:
I was more thinking of introducing Dispose(bool) early on - but even
that can be done at the level of the first class that requires it, I
guess, with a call to base.Dispose() only when disposing is true.

Even that would be impossible, if the Dispose is implemented explicitly. So
Dispose atleast should be implemented explicitly so that deriving classes
can call the base version while remapping or overriding Dispose.

Also, this can be a versioning issue, if a later version holds an unmanaged
resource directly, and so has to have its own finalizer.

Christof
 
S

Samuel R. Neff

But if Dispose is called like it should be, then the finalizer never
comes into play due to SuppresFinalize(). The reason for the
conditional compilation is that stack trace generation is an expensive
operation.

Sam

------------------------------------------------------------
We're hiring! B-Line Medical is seeking .NET
Developers for exciting positions in medical product
development in MD/DC. Work with a variety of technologies
in a relaxed team environment. See ads on Dice.com.
 
J

Jon Skeet [C# MVP]

Samuel R. Neff said:
But if Dispose is called like it should be, then the finalizer never
comes into play due to SuppresFinalize(). The reason for the
conditional compilation is that stack trace generation is an expensive
operation.

Even queuing things up on the finalizer queue and removing them is
something to avoid if there's no benefit though - that's why I'd make
the whole finalizer conditional.
 
S

Samuel R. Neff

But if you call SuppressFinalize then it's as if the finalizer never
existed.. no?

Sam


------------------------------------------------------------
We're hiring! B-Line Medical is seeking .NET
Developers for exciting positions in medical product
development in MD/DC. Work with a variety of technologies
in a relaxed team environment. See ads on Dice.com.
 
M

Moty Michaely

But if you call SuppressFinalize then it's as if the finalizer never
existed.. no?

Sam

------------------------------------------------------------
We're hiring! B-Line Medical is seeking .NET
Developers for exciting positions in medical product
development in MD/DC. Work with a variety of technologies
in a relaxed team environment. See ads on Dice.com.

Yes,
it's true.
 
J

Jon Skeet [C# MVP]

But if you call SuppressFinalize then it's as if the finalizer never
existed.. no?

No - because SuppressFinalize can't be called until after the object
is created, and part of object creation is putting it onto the
finalizer queue if there's a finalizer.

Basically, there's a small performance hit for having a finalizer
which is always suppressed. It won't be significant in many cases, but
if you're creating millions of such objects, you don't want the
overhead.

Jon
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top