1

Appearently, in java; "the object will not be collected until it gets unreachable again" (What if a finalizer makes an object reachable?). I assume the same holds in C#, but does it?

A quick example:

public static void MyWeakCache
{
    private static readonly ICollection<WeakReference<MyFinalizableObject>> cache;
    private static readonly IList<MyFinalizableObject> pendingRemoval;

    // Other implementation

    public static void Register(MyFinalizableObject myObj)
    {
        cache.Add(new WeakReference<MyFinalizableObject>(myObj));
    }

    public static void Deregister(MyFinalizableObject myObj)
    {
        pendingRemoval.Add(myObj);
    }
}

public class MyFinalizableObject
{
    public MyFinalizableObject() 
    {
        MyWeakCache.Register(this);
    }

    ~MyFinalizableObject()
    {
        // Object is reachable again after this call.
        MyWeakCache.Deregister(this);
    }
}
Community
  • 1
  • 1
Henrik
  • 83
  • 5
  • 1
    This is true for C# as well – Kevin Gosse May 02 '17 at 17:55
  • 1
    @Henrik, finalizers are not recommended for Java or C# as they can not be guaranteed to be called. Use the IDisposable interface for C# and the AutoCloseable interface for Java. https://softwareengineering.stackexchange.com/questions/288715/is-overriding-object-finalize-really-bad https://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.100).aspx – Novaterata May 02 '17 at 17:59
  • @Novaterata Are they not guaranteed to be called when garbage collection occurs? – Henrik May 02 '17 at 18:02
  • 1
    @Henrik No, please read those articles. Acording to Raymond Chen "A correctly-written program cannot assume that finalizers will ever run." https://blogs.msdn.microsoft.com/oldnewthing/20100809-00/?p=13203/ – Novaterata May 02 '17 at 18:02
  • but you need to see how GB work if it diden't remove it this will be accessiable – Shahrooz Ansari May 02 '17 at 18:07
  • @Novaterata I do use a finalizer in my code, but not in such a contrived way as in the example I posted (I also don't pass 'this' out). In my case I should be ok, as I don't require the finalizers to run, it's just nice if they do. Anyway, it's good to know about this finalizer limitation in the future. – Henrik May 02 '17 at 18:21
  • @KevinGosse Got any reference where this is stated? Not that I don't believe you. – Henrik May 02 '17 at 18:23
  • You can probably find documentation here and there (https://blogs.msdn.microsoft.com/clyon/2006/04/25/object-resurrection/ for instance), but it's logical anyway. If the object gets collected, then what is your reference pointing to? – Kevin Gosse May 02 '17 at 18:53
  • One of the best articles ever written on .NET garbage collection is, sadly, no longer hosted by Microsoft. But you can still read it archived: https://web-beta.archive.org/web/20030623083457/http://msdn.microsoft.com/msdnmag/issues/1100/GCI/. It discusses (among many other things) how objects can be resurrected in the finalizer, and why you should avoid design patterns that will lead to that. – Peter Duniho May 03 '17 at 03:42
  • @PeterDuniho Really cool, thanks. – Henrik May 03 '17 at 19:29

1 Answers1

1

If the finalizer creates a new reference to the object then the object is not garbage collected. But there's no way of knowing when the finalizer will run or if it will run.

That creates a scenario where, for an unknowable period of time between when the last reference to the object is removed and when the finalizer is called, the object is in limbo, sitting in memory with no references to it. The natural flow of garbage collection is that no object should return from this state. It's like bringing Frankenstein to life. He's dead, let nature take its course.

It's interesting but has no practical application because there's no reason to do this. By definition finalizers don't exist to maintain references to objects. The only thing it can accomplish is creating unpredictable behaviors and bugs.

Scott Hannen
  • 27,588
  • 3
  • 45
  • 62