开发者

How should I ensure disposal of possibly disposable objects?

I am working on a .NET project, which needs to interact with some user defined classes - reffered to as "jobs". All job classes must implement a 开发者_开发技巧specific interface IJob in order order for the library to consume them. Sometimes a job class might hold unmanaged resource, which needs to be explicitly disposed.

How should I ensure that all jobs are properly disposed after use, if I do not know in advance if the job needs explicit disposal? I have a few ideas myself, but would like to hear your comments/suggestions:

  1. Make IJob : IDisposable, forcing all jobs to implement a Dispose() method. This will allow me to work with jobs in using blocks, but as most jobs are not expected to need explicit disposal, this might add unneeded confusion for the client developers.

  2. Do all work involving jobs in try-finally blocks, and use finally to ensure that Dispose() is called if the job implements IDisposable. This makes it easier for clients to implement a new job class - by not having to implement an empty Dispose() method - but it also hides the fact that the library knows and cares about disposable jobs.

After writing this up, I tend to lean towards solution #1, but I still think it would be nice to see alternative solutions, and additional pros/cons to the two I already have in mind.


There is a precedent: The Stream base class is IDisposable nad therefore all Streams descendants are. But MemoryStream doesn't need Disposing.
But don't aim for try/finally, the using() { } block is a more convenient shorthand.

So your choice is: Do you want all Jobs to be IDisposable or just some?

The first option incurs a small overhead, the second one makes it easier to forget Dispose (using) when it is necessary.


#2 is how the foreach construct works. It is also how Autofac's container disposal works.

The semantic difference is whether you say that a job itself is disposable, or whether an implementation might be disposable.

It is clear from your example that the former is not true, that jobs are not inherently disposable. Therefore, I recommend #2, but with an extension method to centralize the try/finally:

public static void Execute(this IJob job)
{
    try
    {
        job.Run();
    }
    finally
    {
        var disposableJob = job as IDisposable;

        if(disposableJob != null)
        {
            disposableJob.Dispose();
        }
    }
}


I think of it this way. I'd rather a developer implement an empty Dispose method than forget to implement a necessary Dispose method.


I would go with #2 and document that any disposable object will be disposed. Basically if you take ownership of an object you are obligated to dispose of objects that implement IDisposable.

If you read Effective C#/ More Effective C#, Bill Wagner give the same advice (which I agree with obviously ;-)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜