I was wondering if the following code shows a bad practice (about interface inheritance):
public interface IFoo : IDisposable
{
void Test();
}
public class TestImpl : IFoo
{
public void Test()
{
// do something
}
public void Dispose()
{
// disposing my dependencies
}
}
public class FooFactory
{
public IFoo CreateFoo()
{
return new TestImpl();
}
}
public class Client
{
public void Main()
{
FooFactory factory = new FooFactory();
using(IFoo foo = factory.CreateFoo())
{
// do stuff then auto-dispose
foo.Test();
}
}
}
Here, I wanted two things: 1. Use the C#'s using statement so I can dispose my concrete object's dependencies elegantly (no need to cast anything to IDisposable). 2. Use a factory method to create a concrete object, so I can work only with the interfaces.
Separated, both are known good practices, but together? I didn't find anything saying it's wrong here http://msdn.microsoft.com/en-us/library/ms229022.aspx (MSDN - Interface Design), but I think it doesn't sound good...
I would appreciate any comment about this. If it's a bad practice, what kind of issues I would run into using this approach?
Thanks!
We can inherit enormously more classes than Inheritance, if we use Interface. Methods can be defined inside the class in case of Inheritance. Methods cannot be defined inside the class in case of Interface (except by using static and default keywords). It overloads the system if we try to extend a lot of classes.
Allowing multiple inheritance makes the rules about function overloads and virtual dispatch decidedly more tricky, as well as the language implementation around object layouts. These impact language designers/implementors quite a bit and raise the already high bar to get a language done, stable, and adopted.
Interfaces can inherit from one or more interfaces. The derived interface inherits the members from its base interfaces. A class that implements a derived interface must implement all members in the derived interface, including all members of the derived interface's base interfaces.
The design guidelines for interfaces specifically says: Avoid using marker interfaces (interfaces with no members). Custom attributes provide a way to mark a type. For more information about custom attributes, see Writing Custom Attributes.
In the wild, there is no such thing as a definitely good or bad practice, each has its upsides and downsides.
A practice becomes good or bad only when it is applied to a concrete problem (read: not IFoo
).
public bool IsGood<TContext>(IPractice practice)
where TContext : RealWorldApplication, new();
So, instead of trying to find guidance on MSDN, ask yourself the following question:
Does this solve the problem and make the code simpler to read?
If the answer is yes, go with it.
Personally, I like the approach. If the contract for IFoo
requires proper disposal (think: IGraphicalObject
, IResource
, IConnection
), it's a very good design decision to make this explicit.
Don't be trapped by dogma: programming with interfaces makes you less dependent on concrete implementations, but programming only with interfaces can be a nightmare. Be reasonable, that's it.
You can use Google to find all interfaces that inherit from IDisposable
in .NET Framework itself:
intitle:interface "inherits idisposable" site:msdn.microsoft.com
As I said above, this is normally done for entities that are known to consume resources, such as database connections, unmanaged object wrappers, graphical objects, et cetera.
Imposing implementing Dispose()
on a class that has nothing to dispose of would be a bad idea.
In this case it's better to leave it optional and check for IDisposable
support, as suggested by Peter.
This is perfectly valid. That's exactly what interfaces are for. They define contracts. A contract can be built using several sub contracts.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With