Is it possible to define an Interface with optional implementation methods? For example I have the following interface definition as IDataReader in my core library:
public interface IDataReader<T> {
void StartRead(T data);
void Stop();
}
However, in my current implementations, the Stop() method has never been used or implemented. In all my implementation classes, this method has to be implemented with throw NotImplementedExcetion() as default:
class MyDataReader : IDataReader<MyData> {
...
public void Stop()
{
// this none implementaion looks like uncompleted codes
throw NotImplementedException();
}
Of course, I can remove the throw exception code and leave it empty.
When I designed this data reader interface, I thought it should provide a way to stop the reading process. Maybe we will use Stop() sometime in the future.
Anyway, not sure if it is possible to make this Stop() method as an optional implementation method? The only way I can think is to either to define two interfaces one with stop and another without such as IDataReader and IDataReader2. Another option is to break this one into to interfaces like this:
interface IDataReader<T> {
void StartRead(T data);
}
interface IStop {
void Stop();
}
In my implementation cases, I have to cast or use as IStop to check if my implementation supports Stop() method:
reader.StartRead(myData);
....
// some where when I need to stop reader
IStop stoppable = reader as IStop;
if (stoppable != null ) stoppable.Stop();
...
Still I have to write those codes. Any suggestions? Not sure if there is any way to define optional implementation methods in an interface in .Net or C#?
For info, another approach fairly common in the BCL is
Supports*on the same interface, i.e.(examples of this, for example, in
IBindingList).I’m not pretending that it is “pure” or anything, but it works – but it means you now have two methods to implement per feature, not one. Separate interfaces (
IStoppableReader, for example) may be preferable.For info, if the implementation is common between all implementations, then you can use extension methods; for a trivial example:
(or the equivalent for your interface). If you provide a more specialized version against the concrete type, then it will take precedence (but only if the caller knows about the variable as the concrete type, not the interface). So with the above, anyone knowingly using a
List<T>still usesList<T>‘s version ofAddRange; but if the have aList<T>but only know about it asIList<T>, it’ll use the extension method.