Search code examples
c#disposeidisposablefactory-pattern

Should factory keep track of created IDisposable objects?


Consider the following simple factory example:

public class MyFactory : IMyFactory
{
    public MyObject CreateObject()
    {
        return new MyObject();
    }
}

In this example, MyObject implements the IDisposable interface. Typically I would expect the consuming program to use this as follows:

// Use using to properly dispose of MyObject
using (MyObject obj = myFactory.CreateObject())
{
    // ...
}

Is it common practice to expect the developer consuming the Factory to handle disposal like this? Or should the Factory keep a list of objects it has created and make sure they are cleaned up periodically, or, possibly when the factory is disposed?


Solution

  • A type implementing IDisposable provides a way for the consumer of the type to deterministically clean up any unmanaged resources used by the type. E.g., when a FileStream is disposed the underlying OS file handle is closed.

    Any properly implemented type that directly uses an unmanaged resource (e.g file handle, database connection, native socket etc.) will also have a finalizer to release the unmanaged resource when the object is garbage collected. It is up to the consumer of the type to either use IDisposable to deterministically release the unmanaged resource or simply wait for the garbage collector to do it. In most cases you want to go the deterministic route. E.g., you do not want to wait for the garbage collector before a file becomes accessible from other processes. You want to close the file as soon as you are done working with that file.

    So the garbage collector in combination with finalizers will perform the task that you try to delegate to your factory and because your factory is not the garbage collector you will probably have a very hard time to actually implement this "tracking and automatic clean up".

    So my primary answer to your question is, no, the factory should not keep track of created IDisposable objects.

    However, if your factory is some sort of container that controls the lifetime of the created objects you can make the factory itself IDisposable and then dispose all created objects on disposal. This is a common pattern in dependency injection containers that are used in response-request cycles like in web applications. The container is created at the start of the request and disposed when the response is complete. The consumers of the types created by the factory are oblivious to the fact the some of the types have to be disposed when the request ends.