2

I am asking that if a class A inherits from InterfaceA and IDisposable, then whether it's good/necessarily that InterfaceA should inherit from IDisposable?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Imran Qadir Baksh - Baloch
  • 32,612
  • 68
  • 179
  • 322

3 Answers3

2

No.

Just because an implementing class inherits from IDisposable does not mean that its interfaces should implement IDisposable.

IDisposable is meant to be used as a way for a class to release un-managed resources. There's a good chance that your interface doesn't require an implementing class to use un-managed resources, so there'd be no reason for an implementation to implement IDisposable.

Justin Niessner
  • 242,243
  • 40
  • 408
  • 536
  • Thanks. But what if I use this interface in DI container. – Imran Qadir Baksh - Baloch Jan 27 '13 at 06:38
  • @user960567 That depends on the DI container. But it should be able to figure out that the concrete class implements `IDisposable` and dispose it correctly. – svick Jan 27 '13 at 11:56
  • 3
    If an interface will be returned by a factory, and *any* implementations returned by the factory *might* require `Dispose`, then users of that factory must `Dispose` *every* object returned by that factory which allows it. Omitting `IDisposable` from the interface won't ease caller's obligations; it will merely make it harder for them to satisfy it, and increase the likelihood that they won't. – supercat Jan 27 '13 at 19:34
2

I think that depends on your intended usage. For example, if the user is never going to see the concrete class, only the interface, then they are not going to expect the implementation to implement IDisposable.

The user can do something like:

var disposable = a as IDisposable;
if (disposable != null)
    disposable.Dispose();

But I think most of them won't do that, unless your documentation clearly says that they should.

On the other hand, if you expect the user to primarily work directly with the class, then they will know that the class is IDisposable, so they are likely to dispose it correctly.

You mentioned DI container in a comment. This depends on the specific container, but I think most DI containers will dispose the object when they know you no longer use it. But this assumes the container knows the object is no longer in use (in the case of Castle this most likely means calling Release()) and that they don't use “singleton lifestyle” (in Castle terminology).

svick
  • 236,525
  • 50
  • 385
  • 514
2

Interface IFoo should probably implement IDisposable if it is likely that the last entity which holds a reference to an object instance that implements IFoo and requires cleanup will only know of that instance as an IFoo, and not as its underlying type.

For example, the reason IEnumerator<T> implements IDisposable is that while only a few implementations require cleanup, instances will generally be created by code which calls IEnumerable<T>.GetEnumerator(). Such code will often have no clue whatsoever about the actual type of object GetEnumerator() is going to return; as a consequence, it will have no way of knowing whether or not the object that is returned will require cleanup. Since failure to dispose an enumerator that does require cleanup may have bad consequences, the only safe assumption is that any unknown-type enumerator should be cleaned up if possible.

Although the non-generic IEnumerator does not implement IDisposable, that does not mean that it does not require cleanup. Rather, it means that any code which calls IEnumerable.GetEnumerator() must check whether the object it returned implements IDisposable and, if so, Dispose it. This is rather slow and cumbersome. If IEnumerator implemented IDisposable, code could simply call Dispose whether or not the class needs cleanup; even if Dispose does nothing, calling a do-nothing routine on an interface which is known to be implemented will waste less time than testing for an interface which isn't implemented.

It's important to note that even though very few implementations if IEnumerator require disposal, any code which calls GetEnumerator on unknown implementation of IEnumerable must, for correctness, attempt the cast to IDisposable. The fact that IEnumerable<T>, unlike IEnumerable, implements IDisposable does not add to the obligations of code that calls IEnumerable<T>. Rather, it makes such obligations explicit, and it reduces the cost of complying with them.

supercat
  • 77,689
  • 9
  • 166
  • 211