Implementing IDisposable on factory pattern objects

A

Andrew Falanga

Hi,

I'm reading this article on MSDN, http://msdn.microsoft.com/en-us/library/system.idisposable.aspx,
and it says that (for the base class) the Dispose( ) function should
not be made virtual because you don't want derived classes calling
it. However, that's precisely what I need in a factory pattern. So,
how does one properly implement IDisposable in a factory patterned
base/derived model?

Thanks,
Andy
 
J

Jeroen Mostert

Andrew said:
I'm reading this article on MSDN, http://msdn.microsoft.com/en-us/library/system.idisposable.aspx,
and it says that (for the base class) the Dispose( ) function should
not be made virtual because you don't want derived classes calling
it. However, that's precisely what I need in a factory pattern. So,
how does one properly implement IDisposable in a factory patterned
base/derived model?
The Dispose() method should not be virtual; instead you should provide a
protected Dispose(bool) method that *is* virtual, to which Dispose()
delegates. See http://msdn.microsoft.com/library/b1yfkh5e for more information.
 
A

Andrew Falanga

The Dispose() method should not be virtual; instead you should provide a
protected Dispose(bool) method that *is* virtual, to which Dispose()
delegates. Seehttp://msdn.microsoft.com/library/b1yfkh5efor more information.

Thank you for this article. I hadn't found that one yet (and might
not have found it). I hope you see my response, or someone else does,
I want to make sure that my solution is sound.

After thinking about it my derived classes do not have anything
objects in them that they must free. Indeed, the only objects giving
me difficulty were the objects contained in the base class. So, I've
implemented IDisposable on the base class according to the link I
first posted. Basically, the only place that the Dispose() function
was needed as in the base class. However, I'm wondering if I should
still implement according to the link you've provided because,
although the derived objects don't need to dispose of anything, should
I have a virtual protected Dispose()/override Dispose() in this base<-
derived relationship?

Thanks,
Andy
 
J

Jeroen Mostert

Andrew said:
Thank you for this article. I hadn't found that one yet (and might
not have found it). I hope you see my response, or someone else does,
I want to make sure that my solution is sound.

After thinking about it my derived classes do not have anything
objects in them that they must free.

This is only a valid conclusion if you already know all derived classes that
will ever be. Keep in mind that you can't enforce this -- if a class is
accessible and unsealed anyone can derive from it. Generally it saves more
time assuming that everybody will (possibly including a future you) than to
assume you have complete control and fix the avoidable problems afterwards.
Indeed, the only objects giving me difficulty were the objects contained
in the base class. So, I've implemented IDisposable on the base class
according to the link I first posted.

This is dangerous because any derived class that does need to introduce its
own disposable members is going to have a hard time doing this correctly.
It's still possible using method hiding and re-implementing IDisposable, but
it's not intuitive, nor is it safe (derived classes cannot be forced to call
their parent's Dispose() methods, as they should).
Basically, the only place that the Dispose() function was needed as in
the base class. However, I'm wondering if I should still implement
according to the link you've provided because, although the derived
objects don't need to dispose of anything, should I have a virtual
protected Dispose()/override Dispose() in this base<- derived
relationship?
Yes, because the overhead is negligible compared to the horrible mess you'll
have on your hands if this turns out to be the wrong decision.

This is a standard pattern you should follow because it makes everyone's
life easier. You should only forego a virtual Dispose() if your class is
sealed and thus has no derived classes to worry about in the first place.
 
J

Jeroen Mostert

Jeroen said:
This is only a valid conclusion if you already know all derived classes
that will ever be. Keep in mind that you can't enforce this -- if a
class is accessible and unsealed anyone can derive from it. Generally it
saves more time assuming that everybody will (possibly including a
future you) than to assume you have complete control and fix the
avoidable problems afterwards.


This is dangerous because any derived class that does need to introduce
its own disposable members is going to have a hard time doing this
correctly. It's still possible using method hiding and re-implementing
IDisposable, but it's not intuitive, nor is it safe (derived classes
cannot be forced to call their parent's Dispose() methods, as they should).
The last half of this argument is spurious because, even following the
standard pattern, derived classes cannot be forced to call their parent's
Dispose() methods. It does become easier and more obvious to do, though.
Yes, because the overhead is negligible compared to the horrible mess
you'll have on your hands if this turns out to be the wrong decision.

This is a standard pattern you should follow because it makes everyone's
life easier. You should only forego a virtual Dispose() if your class is
sealed and thus has no derived classes to worry about in the first place.
Footnote to this: note that if you follow this pattern, a derived class that
does not introduce its own disposable members doesn't need to do anything,
in particular it doesn't need to override Dispose(). Everything will just work.
 
A

Andrew Falanga

The last half of this argument is spurious because, even following the
standard pattern, derived classes cannot be forced to call their parent's
Dispose() methods. It does become easier and more obvious to do, though.




Footnote to this: note that if you follow this pattern, a derived class that
does not introduce its own disposable members doesn't need to do anything,
in particular it doesn't need to override Dispose(). Everything will justwork.

Thank you for the responses and explanations.

Andy
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top