Expilicit Interface Implementation
There is always the possibility you might implement interfaces that contain identical members and therefore, have a name clash to contend with.
class Octagon : IDrawToForm, IDrawToMemory
{
public void Draw()
{
Console.WriteLine("Drawing the Octagon!");
}
}
public interface IDrawToForm
{
void Draw();
}
public interface IDrawToMemory
{
void Draw();
}
Octagon oct = new Octagon();
// explicitly.
((IDrawToMemory)oct).Draw();
if (oct is IDrawToMemory dtm)
{
dtm.Draw();
}
When using explicit interface implementation syntax:
class Octagon : IDrawToForm, IDrawToMemory
{
void IDrawToMemory.Draw()
{
throw new NotImplementedException();
}
void IDrawToForm.Draw()
{
throw new NotImplementedException();
}
}
The syntax;
returnType InterfaceName.MethodName(params)
Note that when using this syntax, you do not supply an access modifier, explicitly implemented members are automatically private.
// Error! No access modifier
public void IDrawToMemory.Draw()
{
throw new NotImplementedException();
}
Designing Interface Hierarchies
Interfaces can be arranged in an interface hierarchy. Like a class hierarchy when an interface extends an existing interface, it inherits the abstract members defined by the parent (or parents). Prior to C# 8, derived interfaces never inherit true implementation. Rather, a derived interface simply extends its own definition with additional abstract members. In C# 8, derived interfaces inherit the default implementations as well as extend the definition and potentially add new default implementation.
public interface IDrawable
{
void Draw();
}
public interface IAdvancedDraw : IDrawable
{
void DrawInBoundingBox(int top, int left, int bottom, int right);
void DrawUpsideDown();
}
public class BitmapImage : IAdvancedDraw
{
}
Interface Hierarchies with Default Implementations
When interface hierarchies also include default implementations, downstream interfaces can choose to carry the implementation from the base interface or create a new default implementation.
public interface IDrawable
{
void Draw();
int TimeToDraw() => 5;
}
BitmapImage myBitMap = new BitmapImage();
// This code does not compile
myBitMap.TimeToDraw();
If a downstream interface wants to provide its own default implementation, it must hide the upstream implementation.
public interface IAdvancedDraw : IDrawable
{
…
new int TimeToDraw() => 15;
}
Then BitmapImage class can implement this method.
public class BitmapImage : IAdvancedDraw
{
public new int TimeToDraw() => 15;
…
}
BitmapImage myBitMap = new BitmapImage();
Console.WriteLine(myBitMap.TimeToDraw());
Console.WriteLine(((IDrawable)myBitMap).TimeToDraw());
Console.WriteLine(((IAdvancedDraw)myBitMap).TimeToDraw());