0

I have read some about GC,Finalizers,Managed & Unmanaged Objects,Disposable pattern @StackOverflow.

Currently,I am quite confused about proper usages of GC,Finalizers,Disposable pattern and managed,unmanaged resources terminology.

IMHO there are lots of misleading answers about the subjects mentioned above.

For instance;

I take this post as an example

The accepted answer for this question imply that if we don't call dispose method of a .net object that implements IDisposable interface by default we won't be able to free unmanaged resources.

I think this is a false statement.First there is a concept confusion between managed and unmanaged resources.In my opinion,

Managed resource: any .NET class that implements the IDisposable interface, like Streams and DbConnections.

Unmanaged resource: the stuffing wrapped in the Managed Resource classes. Windows handles are the most trivial examples.

As @kicsit stated at this post

So I ended up with having idea of that all classes that implement IDisposable interface by default such as pen,streamwriter are managed resources which include unmanaged resources inside.

All difference between calling IDispose method explicitly and letting GC do is that one indirectly signaling to the GC that the object can be cleaned up during the next GC , the latter is completely undeterministic.

However when I have a look of Dataset and Datatable classes ,although they implement IDisposable by default they don't own any unmanaged resources inside. This accepted answer also supports my idea.

Quote from answer

The system.data namespace (ADONET) does not contain unmanaged resources. Therefore there is no need to dispose any of those as long as you have not added yourself something special to it.


So my first idea fails.Having a Disposable by default doesn't necessarily mean that class/object has unmanaged resources inside.

Q1)Is it true?

Q2) If I use a class like streamwriter which includes IDisposable interface by default and not call it.Will GC put it Finalization queue and then call Dispose method respectively ?(I mean StreamWriter.Dispose() method which is equivalent to StreamWriter.Close()

Q3) Is finalization queue takes place if we explicitly implement destructor ?

Community
  • 1
  • 1
erhan355
  • 806
  • 11
  • 23
  • 1
    I would recommend taking a look [this blog post by Eric Lippert](https://ericlippert.com/2015/05/18/when-everything-you-know-is-wrong-part-one/). – Will Ray Apr 14 '16 at 20:35

1 Answers1

1

I think the distinction between managed and unmanaged resources you're trying to make here is confusing you.

Let me try to picture things like this:

You have an object, which represents a resource (be it a connection, a handle, anything, managed or not). Let's say it's IDisposable and has a finalizer as well.

You use the object in your code, and at some point you are done with it.

  • If you call the Dispose method, you're basically telling the object you're done with it, and instructing it to free any resource it holds (destroy the handle, close the connection and so on).

    This should be the preferred course of action, ideally done via the using statement.

    A properly implemented dispose pattern will mark the object as not requiring finalization anymore at this point.

  • You neglect to call Dispose and let the object go out of reachability. At some point, it gets spotted by the GC, the GC puts the object into the finalizer queue, the finalizer runs and releases the resources (more on that later), your object goes back to the GC and then gets freed.

    This takes roughly a century. During that time, you have an unreferenced object holding some resource for no good reason. And you're putting pressure on the GC by forcing it to finalize the object.

    Think of this as a failsafe mechanism. The fact that the GC does this dirty work lets you avoid memory/resources leaks, as your resources will eventually get freed. But why wait and put pressure on the system?

Now, you'll read that finalizers are meant for releasing unmanaged resources, and this would be right. Why is that? You don't need to release managed objects, since the GC can take care of these. This is transitive: if you have a chain of managed objects with the last one holding onto an unmanaged reference, only that last one needs special care, and the GC will take care of it... eventually.

Sometimes the disposable pattern is used to perform side effects when you go out of a using scope, be it normally or through exception propagation. This is a good technique, used for deterministic cleanup.
But you can't rely on a finalizer to perform such a side effect. For one, it's called nondeterministically from the finalizer thread, and worse: you can't assume anything about the environment it runs in. That's why you should only execute code which will take care of avoiding memory leaks and freeing unmanaged resources in finalizers. Do the bare minimum of work in a finalizer.


Now, let's see your questions:

Having a Disposable by default doesn't necessarily mean that class/object has unmanaged resources inside. Is it true?

Correct.

If I use a class like streamwriter which includes IDisposable interface by default and not call it.Will GC put it Finalization queue and then call Dispose method respectively ?(I mean StreamWriter.Dispose() method which is equivalent to StreamWriter.Close()

Absolutely not. The finalizer will be called in that case, in a dubious environment. The IDisposable.Dispose method will not be called.

But there's a very common pattern, which is a variation of the following:

class Foo : IDisposable
{
    ~Foo() => Dispose(false);
    public void Dispose() => Dispose(true);

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            // Do whatever you want to perform deterministically
            GC.SuppressFinalize(this); // No need to finalize anymore
        }

        // Free any unmanaged resource you hold.
        // Make sure you don't throw here, or kiss your process goodbye.
    }
}

I guess you could say the Dispose(bool) method is called on finalization here, but don't confuse this with the IDisposable.Dispose one.

Is finalization queue takes place if we explicitly implement destructor ?

Yes, the object will be placed on the finalization queue if it declares a destructor, AKA a finalizer. I don't like the destructor term since it has a very different meaning from C++, better call that a finalizer, so the difference stands out.

Lucas Trzesniewski
  • 50,214
  • 11
  • 107
  • 158
  • You assert that any object is going to be placed on the finalization queue if and only if an explicit finalizer is implemented.I am at the same point with you too.But, How do then GC call finalizer if even I don't implement finalizer explicitly and neglect to call StreamWriter.Dispose()/Close().As far as I know,StreamWriter keeps unmanaged resources.So they must be disposed somehow. It should somehow execute Dispose()/Close() method to release unmanaged resources? But how ? – erhan355 Apr 15 '16 at 08:43
  • `StreamWriter` doesn't need unmanaged resources, it just holds a reference to a `Stream`, which in turn may hold unmanaged resources, depending on the stream type... sort of, there's also [this helper class](http://referencesource.microsoft.com/#mscorlib/system/io/streamwriter.cs,94755b717c1c0c8c) which does have a finalizer if the user chose to enable [MDA](https://msdn.microsoft.com/en-us/library/d21c150d.aspx). BTW the link contains the `StreamWriter` code, take a look. – Lucas Trzesniewski Apr 15 '16 at 08:58