I asked something similar but still I haven't got a clear idea. My objective is to partially imp开发者_开发知识库lement an interface in C#.
Is it possible? Is there any pattern to achieve this result?
An interface defines a contract. You have to fulfill that contract by implementing all of its members if you want to use it.
Maybe the use of an abstract class would work best for you, that way you can define some default behavior while allowing overrides where you need to.
You can throw NotImplementedException
for the methods you don't want to implement or NotSupportedException
for the methods you can't implement.
It's preferable to not do this, but there are places in the .NET framework where classes throw NotSupportedException
s and the design of Stream
pretty much forces you to throw this exception for some methods.
From MSDN about NotSupportedException:
The exception that is thrown when an invoked method is not supported, or when there is an attempt to read, seek, or write to a stream that does not support the invoked functionality.
yes you can partially implement interface if you are using abstract class something like this:
public interface myinterface
{
void a();
void b();
}
public abstract class myclass : myinterface
{
public void a()
{
///do something
}
public abstract void b(); // keep this abstract and then implement it in child class
}
As others have said an interface should be fully implemented (although there are ways around this like throwing NotSupportedExceptions)
You should take a look at The Interface Segregation Principle (one of the SOLID priciples that Robert Martin discusses) and figure out if you actually need multiple interfaces that classes can then choose which ones to implement
Like the other posts, throwing an exception in addition to hiding the member is your best bet.
interface IPartial
{
void A();
void B();
}
class Partial : IPartial
{
public void A()
{
// Implementation here
}
void IPartial.B()
{
throw new NotImplementedException();
}
}
class Main
{
Main()
{
Partial t = new Partial();
t.A();
t.B(); // Compiler error
IPartial s = new Partial();
s.A();
s.B(); // Runtime error
}
}
It is entirely possible that implementation of SOME of the methods in the Interface are common to a group of classes, while the rest need to be uniquely implemented.
Using abstract classes kind of require you to re-declare the unimplemented methods using the abstract methods, which is redundant as you have the declaration already in the interface. Exceptions approach is not the best either because if you are not careful, you will get to know what you have "missed" implementing only at runtime when you see the error message.
Here is a way to do this without abstract classes and without using Exceptions. One of the methods in the interface is implemented in a separate (perhaps common) way. Thus you are only required to implement the "rest" in your Implementation class.
interface Interface
{
void A();
void B();
}
class PartialImplementer
{
public void B()
{
// common implementation
}
}
class Implementation : PartialImplementer, Interface
{
public void A()
{
// unique implementation
}
}
I had a bunch of Query classes with a common interface, but I was not implementing all the methods. The methods I did not implement throw NotImplementedException
. But I did not like it.
So I broke my interface into 4 interfaces like this:
Before
public interface ICrudQueries<TIndexViewModel, TDetailsViewModel, TCreateViewModel, TEditViewModel>
{
Task<TIndexViewModel> GetIndexViewModel(TIndexViewModel viewModel = default);
Task<TDetailsViewModel> GetDetailsViewModel(int id);
Task<TCreateViewModel> GetCreateViewModel();
Task<TCreateViewModel> SetSelectLists(TCreateViewModel viewModel);
Task<TEditViewModel> SetSelectLists(TEditViewModel viewModel);
Task<TEditViewModel> GetEditViewModel(int id);
}
After
public interface IDetailsQuery<TDetailsViewModel>
{
Task<TDetailsViewModel> GetDetailsViewModel(int id);
}
public interface ICreateQuery<TCreateViewModel>
{
Task<TCreateViewModel> GetCreateViewModel();
Task<TCreateViewModel> SetSelectLists(TCreateViewModel viewModel);
}
public interface IEditQuery<TEditViewModel>
{
Task<TEditViewModel> SetSelectLists(TEditViewModel viewModel);
Task<TEditViewModel> GetEditViewModel(int id);
}
public interface IIndexQuery<TIndexViewModel>
{
Task<TIndexViewModel> GetIndexViewModel(TIndexViewModel viewModel = default);
}
Now I can implement them separately and I don't have to throw NotImplementedException
. I can implement one or more on the same class.
You can even use the original interface as-is like this!
/// <summary>
/// Enforce good practice and naming standards for ViewModel Query classes.
/// Allow allow partial implementation by using any of the other interface(s).
/// </summary>
public interface ICrudQueries<TIndexViewModel, TDetailsViewModel, TCreateViewModel, TEditViewModel> :
IIndexQuery<TIndexViewModel>,
IDetailsQuery<TDetailsViewModel>,
ICreateQuery<TCreateViewModel>,
IEditQuery<TEditViewModel>
{
}
精彩评论