C# – Singleton with finalizer but not IDisposable

cidisposablenetsingleton

This is what I understand about IDisposable and finalizers from "CLR via C#", "Effective C#" and other resources:

  • IDisposable is for cleaning up managed and unmanaged resources deterministically.
  • Classes that are responsible for unmanaged resources (e.g. file handles) should implement IDisposable and provide a finalizer to guarantee that they are cleaned up even if the client code does not call Dispose() on the instance.
  • Classes that are responsible for managed resources only should never implement a finalizer.
  • If you have a finalizer then you must implement IDisposable (this allows client code to do the right thing and call Dispose(), while the finalizer prevents leaking resources if they forget).

While I understand the reasoning for and agree with all of the above, there is one scenario where I think it makes sense to break these rules: a singleton class that is responsible for unmanaged resources (such as providing a single point of access to particular files).

I believe it is always wrong to have a Dispose() method on a singleton because the singleton instance should live for the life of the application and if any client code calls Dispose() then you are stuffed. However, you want a finalizer so that when the application is unloaded the finalizer can clean up the unmanaged resources.

So having a singleton class with a finalizer that does not implement IDisposable seems to me to be a reasonable thing to do, yet this type of design is counter to what I understand are best practices.

Is this a reasonable approach? If not, why not and what are the superior alternatives?

Best Answer

If the unmanaged resource is released only on application exit you don't even need to worry with a finalizer since the process unload should deal with this for you anyway.

If you have multiple app domains and you want to deal with an app domain unload that's one possible issue but possibly one you don't need to care about.

I second those saying that this design is possibly not the right thing to do (and will make it harder to fix is subsequently you find that you do actually need two instances) Create the object (or a lazy loading wrapper object) in your entry point and pass it through the code to where it is needed making it clear who is responsible for providing it to whom, then you are free to change the decision to use only one with little effect to the rest of the code (which uses what it gets given)