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?

Jules
  • 4,319
  • 3
  • 44
  • 72
  • 4
    Read this: http://msdn.microsoft.com/en-us/library/ms973837.aspx –  Jun 15 '10 at 14:20
  • With regard to the `Font` class, it's actually used for two very different purposes in .net; it encapsulates a set of information about a font (family, size, style, etc.) and it also encapsulates a GDI find object. The `Font` property of a control is only interested in the former information; controls won't care if their `Font` property is set to a font which is `Dispose`d (even if the `Dispose` occurs before the property is set!) Consequently, if one wishes to have a field that one will use for setting control `Font` properties, one could create a `Font` for it and then... – supercat Jun 27 '12 at 16:18
  • ...immediately `Dispose` it. A somewhat odd pattern, to be sure, but fundamentally indicative of the fact that .net should have used a `FontInfo` class or struct for controls' `Font` property. – supercat Jun 27 '12 at 16:19

5 Answers5

8

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
  • 61,059
  • 10
  • 88
  • 148
4

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.

Dave
  • 4,420
  • 1
  • 34
  • 39
Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
  • 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 Jun 15 '10 at 14:03
  • 1
    Note that you cannot assume that any object exists other than the object itself being finalized. – Spence Jun 15 '10 at 14:04
  • @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 Jun 15 '10 at 14:42
  • 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 Jun 15 '10 at 18:54
1

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

Adam Houldsworth
  • 63,413
  • 11
  • 150
  • 187
1

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
  • 47,849
  • 13
  • 107
  • 150
0

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
  • 28,526
  • 15
  • 68
  • 103