Disposing of the IDisposable implementation
Posted by Davy Brion on June 17th, 2008
Everytime i need to implement the IDisposable interface i have to lookup the recommended way of doing so. That in itself is a bad sign, so i figured i might as well get rid of this by putting the implementation in a reusable base class, based on the officially recommended way:
public abstract class Disposable : IDisposable
{
private bool disposed;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
DisposeManagedResources();
}
DisposeUnmanagedResources();
disposed = true;
}
}
protected void ThrowExceptionIfDisposed()
{
if (disposed)
{
throw new ObjectDisposedException(GetType().FullName);
}
}
protected abstract void DisposeManagedResources();
protected virtual void DisposeUnmanagedResources() {}
}
So now i can simply inherit from Disposable, and i just need to implement the two abstract methods. Here’s a made up example to illustrate this:
public class MyExpensiveResource : Disposable
{
private FileStream fileStream;
private MemoryStream memoryStream;
public MyExpensiveResource(string path)
{
fileStream = new FileStream(path, FileMode.Open);
memoryStream = new MemoryStream();
}
public void DoSomething()
{
ThrowExceptionIfDisposed();
// ... something
}
protected override void DisposeManagedResources()
{
if (fileStream != null) fileStream.Dispose();
if (memoryStream != null) memoryStream.Dispose();
}
}
Obviously, you can’t use the Disposable base class if you’re already inheriting from another base class so in that case you’d still have to implement the IDisposable interface.
Update: Here’s a thread-safe version of this idea.
June 18th, 2008 at 12:16 am
Actually the method name DisposeExpensiveObjects is a bit misleading. Dispose is meant for releasing unmanaged resources; OS handles, network connections etc, they dont have to be expensive just outside the reach of the garbage collector.
June 18th, 2008 at 8:44 am
well, you should dispose each object you contain that implements IDisposable… but yeah, there are a lot of classes that implement that interface without necessarily being that expensive so that name is not really correct.
Maybe a simple DisposeObjects() would actually be better?
June 18th, 2008 at 10:54 am
I think there still has to be a better way. Maybe some AOP implementation?
June 18th, 2008 at 11:03 am
is that a challenge?
seriously though, an AOP solution would be nice, but i don’t know how well that would work… you’d have to make your type implement the IDisposable interface (which is possible with the Composite aspect in Postsharp) but then in your aspect you’d have to be able to recognize which members you’d have to dispose. I’m not sure how you could do that without resorting to reflection, which i’d rather not use in a Dispose method
June 18th, 2008 at 11:24 am
Maybe something like:
interface ICleanDisposable: IDisposable
{
void DisposeOjects();
void ClearReferences();
}
June 18th, 2008 at 11:29 am
ah, so you’d have the type implement the ICleanDisposable interface instead of the IDisposable interface and then from the AOP aspect you’d reference the target class through the interface type and call the DisposeObjects() and ClearReferences() methods at the appropriate time?
That would certainly avoid the multiple inheritance issue
June 18th, 2008 at 11:36 am
and then we get drunk
June 18th, 2008 at 11:38 am
June 18th, 2008 at 11:52 am
Actually, that still won’t be perfect… if your type implements the ICleanDisposable interface, you’re still required to provide a Dispose method to fullfil the IDisposable requirements that ICleanDisposable brings with it.
If the aspect implements the Dispose method, it won’t be known at compile time since postsharp weaves the aspect code in after it’s been compiled. So you wouldn’t be able to compile to code due to the missing required Dispose method
June 22nd, 2008 at 12:52 am
Here is how I see it:
- the ICleanDisposable doesn’t inherit from IDisposable
- the Disposable aspect implements the IDisposable interface on the aspected class (through a composite aspect with Postsharp)
- In order to call the Dispose() method implemented by the aspect in your code, you will need to use the following method provided by Postsharp:
K Post.Cast(T myObject)
Using this method will allow your code to compile. At compilation-time, Postsharp will check if myObject (of type T) can really be casted to the K type (IDisposable in our case).
The problem with this approach is that you can’t use the using pattern easily. With the following code:
// Toto is a class implementing ICleanDisposable and which has the Disposable aspect
using (var toto = Post.Cast(new Toto()))
{
// do something
}
you won’t be able to call specific methods on the toto instance, as it will be casted to IDisposable… I guess that if we resort to using an old-school try-finally, we could get it to work as expected, but at the cost of making the code less readable.
June 22nd, 2008 at 10:59 am
yeah… code readability is very important to me though, so that’s not a direction i’m willing to take
inheriting from Disposable works pretty well for me so far… I always try to avoid large inheritance hierarchies, and i only use class inheritance where it makes sense to me. So i don’t often run into to the issue where i can’t inherit from Disposable. Unless i have to extend a type i don’t have the source to, but in those cases i prefer composition over inheritance (if possible).
June 30th, 2008 at 1:13 am
The full disposable semantics are only required if you are holding an unmanaged resource.
If you are holding only managed resources, you don’t care about that, and can leave the GC to do all the work
June 30th, 2008 at 4:47 am
This should have had more kicks
July 2nd, 2008 at 7:47 pm
To avoid multiple inheritence one could use a nested class that calls the disposing methods in its parent class and return an instance of the nested class from a context initialising method. Some sort of interface is best defined for the class managing the resources, and an abstract baseclass for the nested class wouldn’t hurt either.
Client code would change from :
using(MyExpensiveResource resource = new MyExpensiveResource())
{
resource.DoSomething()
}
to :
MyExpensiveResource resource = new MyExpensiveResource()
using(resource.AccessResources())
{
resource.DoSomething()
}
AccessResources needs to initialise the resources and return an instance of the nested class that implements idisposable. MyExpensiveResource would probably change name to MyExpensiveResourceManager at this time, but we are discussing a case where the elegant Disposable solution doesn’t work.
July 10th, 2008 at 1:59 pm
[...] IDisposable (rarely) we have to look up the recommended pattern. Therefore he came up with an abstract base class that provides the proper plumbing and method signatures. All it takes is deriving from this [...]
July 23rd, 2008 at 5:48 am
[...] IDisposable (rarely) we have to look up the recommended pattern. Therefore he came up with an abstract base class that provides the proper plumbing and method signatures. All it takes is deriving from this utility [...]
August 16th, 2008 at 8:44 pm
[...] If you can, try to put this pattern into a reusable base class and make your Disposable Managed Resource holding types inherit from this. An example of this approach can be found here. [...]
December 14th, 2008 at 1:37 pm
[...] Disposing of the IDisposable implementation [...]