views:

173

answers:

5

(1) I've read a lot of questions about IDisposable where the answers recommend not using Finalize unless you really need to because of the process time involved.
What I haven't seen is how much this cost is and how often it's paid. Every millisecond? second? hour, day etc.

(2) Also, it seems to me that Finalize is handy when its not always known if an object can be disposed. For instance, the framework font class. A control can't dispose of it because it doesn't know if the font is shared. The font is usually created at design time so the user won't know to dispose it, therefore finalize kicks in to finally get rid of it when there are no references left. Is that a correct impression?

+5  A: 

The main problem with finalize is that it blocks an object from being garbage collected. Instead, the finalizer is called, and the object collected "on the next run". Well, technically IIRC the finalizer runs a list of objects in a separate thread. Anyhow, this is not an "every ms" issue, more an "multiple GC runs needed to get rid of the objects.

TomTom
Better explanation than what I could give.
Meiscooldude
+3  A: 

Finalize is conceptually different than Dispose. Finalize can only free unmanaged resources. Dispose can free managed and unmanaged resources. You should use each as appropriate. (Note that a class with a Finalizer should always implement IDisposable).

Dispose must be called explicitly; Finalize can only be called by the GC.

Update: See my blog post on How to Implement IDisposable and Finalizers: 3 Easy Rules.

Stephen Cleary
Thats not quite correct. You should keep the finalizer short but if you need to do work there you can. (debugging routines come to mind)
Spence
Note that you cannot assume that any object exists other than the object itself being finalized.
Spence
@Spence - your second comment is why your first comment is not normally possible. ;) There are a handful of exceptions, such as `Console.WriteLine`, but as a general rule, what I call "shutdown logic" is only possible in `Dispose` and not a Finalizer.
Stephen Cleary
I think Stephen's answer is generally correct. Sure, you could put debugging routines in `Finalize`, but that's what I would call a fringe case. And generally speaking I would avoid doing any kind of work that is not related to cleaning up unmanaged resources. +1 by the way.
Brian Gideon
A: 

Finalize is extremely useful as a double check. If a crash or someone's bad code doesn't dispose your object before it goes out of scope, guarantee that its resources will be released in the finalizer.

You can do some fancy footwork in your disposer though by calling GC.SuppressFinalize(this) which will allow you to write a method which will work in both situations and give you a guarantee that the code will work nicely.

You could even fire an MDA if you were writing a framework to remind people that they should dispose your object.

The penalty of the finalizer is basically that you end up pushing your object into the level 2 queue which takes longer to run. If you are consistently using objects and they are finalizing this could result in a level 2 collection running more often than neccessary just to run your finalizer threads.

Spence
+1  A: 

I've got a blog post about IDisposable and Finalizing - not about the performance though.

Adam
+1  A: 

I'll answer your second question.

No, Finalize should not be used in this manner. In fact, with the exception of only a very few fringe cases, you should only override Finalize (or declare a destructor in C#) if the class directly holds unmanaged resources.

The issue you described is one of ownership. The owner of an IDisposable class is responsible for its lifetime and the decision of when to call Dispose. Other parts of code are free to use that class, but since they cannot claim ownership they should not participate in the lifetime management of that class.

Unfortunately I am not very familiar with the Font class nor how it might relate to the specific scenario that was the impetus for your question, but I can make a general statement that might apply to you. If your code did not create the instance (via the constructor) directly then your code should not be considered the owner. In that case you can assume the responsibility for disposal is left to something else.

Brian Gideon