Is there any way to reduce the amount of boilerplate code for IDisposable?
My project has many reader and writer classes. I started implementing IDisposable, but I believe that it adds many boilerplate code to my classes. For each of the classes, I need to implement:
- A destructor.
- A Dispose() method.
- A Dispose(bool disposing) method.
- A "bool disposed" field.
- A check to see if the object is already disposed on every single public method.
- Documentation (since I have the documentation flag enabled and the compiler warns otherwise).
My questions:
Is it worth to implement IDisposable? Previously, I used my classes like:
using (Stream s = File.OpenRead("myfile.bin"))
x = new SomethingReader(s).ReadSomething();
With IDisposable, it doesn't improve much:
using (SomethingReader r = new SomethingReader(File.OpenRead("myfile.bin")))
x = r.ReadSomething();
Can I ONLY implement the Dispose() method?
My class doesn't use unmanaged resources, so Dispose(false) does nothing. Since what I'm cleaning is IDisposable too, suposedly calling my 开发者_开发知识库methods after the object has been disposed should throw a ObjectDisposedException since I'm using an already disposed object.
If you recommend implementing the full IDisposable pattern, is there any way to reduce the boilerplate code?
EDIT: Since some answers recommend sealing the class, I can confirm that, in fact, there isn't any problem by sealing the class.
If you're not holding unmanaged resources directly (i.e. even SafeHandle is not holding them directly), then in general:
- Don't implement the finalizer
- Don't implement Dispose(bool)
- DO mark your class as sealed.
It is a great pity that for years all the widely distributed documentation for IDispose was intended for people writing interop libraries (i.e. the .NET framework authors themselves), and completely ignored a much more common usage pattern for everyone else.
Things have improved, and there is now a more lightweight pattern recognised by fxcop (VS Code Analysis) for sealed types: http://msdn.microsoft.com/en-us/library/ms244737%28VS.80%29.aspx
You do not need to implement the full pattern if you are not using unmanaged resources. There is however one side benefit to the pattern. If someone wants to extend your class they can override Dispose(bool)
and then call base.Dispose(true)
to make sure all resources are disposed.
You could inherit from Component assuming you don't need a different base class. But, if you aren't doing anything too special you could just use the Dispose
method. As ChaosPandion pointed out this could cause problems is someone else tries to extend your class later so you may want to seal your implementations.
If someone tries to extend the class by overriding Dispose(boolean) and you haven't implemented it, that will fail. But if they try overriding Dispose(), that will work. I don't see any reason the class should need to be sealed if one doesn't expect descendant classes to directly control any unmanaged resources.
精彩评论