Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is it not a good idea to serialize an object in its finalizer?

Tags:

c#

finalizer

In the book Headfirst C#, I get the point of view that "it's not a good idea to serialize an object in its finalizer, since serialization requires the whole object tree to be in the heap, but you may end up with missing vital part of your program because some objects might’ve been collected before the finalizer ran."

My question is that since my object get a reference to others (that means there is at least one reference to other objects) , how could they be garbage-collected before my finalizer runs?

like image 886
Hohenheim Avatar asked Aug 29 '15 12:08

Hohenheim


2 Answers

Because the garbage collector does not define any order of running finalizers, and doesn't care if your objects are finalized out of order.

By the time your finalizer runs, the GC has already decided that it and every object it references are unreachable, and thus all of those child objects will also be collected. Each of those objects is added to the finalizer queue, but there is no guarantee that the GC will handle them in any outwardly-sensible order.

That's one of the limitations of what you can do in a finalizer: you have to assume all of your child objects could have been destroyed already. The documentation for Object.Finalize calls this out explicitly:

The finalizers of two objects are not guaranteed to run in any specific order, even if one object refers to the other. That is, if Object A has a reference to Object B and both have finalizers, Object B might have already been finalized when the finalizer of Object A starts.

like image 133
Michael Edenfield Avatar answered Sep 30 '22 05:09

Michael Edenfield


The problem with finalizers is that they provide very few guarantees:

  • they're not guaranteed to ever run
  • you can't predict when they will run
  • when they do run, it's possible that some objects they reference have already been finalized, so your object might not be in a valid state

Eric Lippert has two great blog posts about this:

  • When everything you know is wrong, part one
  • When everything you know is wrong, part two

In any case, 99% of the classes you'll ever write should probably not have a finalizer at all. There are very few cases where they're actually necessary. If you need to perform cleanup after you're done using an object, implement IDisposable instead, which at least you can control in a deterministic way.

like image 21
Thomas Levesque Avatar answered Sep 30 '22 05:09

Thomas Levesque