C# - Interface
An interface is like a contract. In the human world, the contract between the two or more humans binds them to act as per the contract. In the same way, the interface includes the declaration of one or more functionalities. Entities that implement the interface must define functionalities declared in the interface. In C#, a class or a struct can implement one or more interfaces.
In C#, an interface can be defined using the interface keyword. Interfaces can contain methods, properties, indexers, and events as members.
Consider the following IPen
interface that declares some basic functionality for a pen.
interface IPen
{
string Color { get; set; }
bool Open();
bool Close();
void Write(string text);
}
In C#, you cannot use any access modifier for any member of an interface. All the members by default are public members. If you use an access modifier in an interface then the C# compiler will give a compile-time error "The modifier 'public/private/protected' is not valid for this item". (Visual Studio will show an error immediately without compilation.)
interface IPen
{
public string Color { get; set; } //error
protected bool Open(); //error
private bool Close(); //error
protected internal void Write(string text);//error
}
An interface can only contain declarations but not implementations. The following will give a compile-time error.
interface IPen
{
string Color { get; set; }
bool Open();
bool Close();
void Write(string text){
Console.Write(text); //error: cannot implement method
}
}
Implementing an Interface
A class or a Struct can implement one or more interfaces using colon (:).
Syntax:
<Class or Struct Name> : <Interface Name>
For example, the following class implements IPen
interface implicitly.
class Cello : IPen
{
public string Color { get; set; }
private bool isOpen = false;
public bool Close()
{
isOpen = false;
Console.WriteLine("Cello closed for writing!");
return isOpen;
}
public bool Open()
{
isOpen = true;
Console.WriteLine("Cello open for writing!");
return isOpen;
}
public void Write(string text)
{
//write text if open
if(isOpen)
Console.WriteLine("Cello: " + text);
}
}
In the above example, the Cello
class implements the IPen
interface. It defines all the members of the IPen
interface with public access modifier. However, other non-interface members of the class can have any access modifiers e.g. Cello
class.
Explicit Interface Implementation
Explicit implementation is useful when class is implementing multiple interface thereby it is more readable and eliminates the confusion. It is also useful if interfaces have same method name coincidently.
You can implement interface explicitly by prefixing interface name with all the members of an interface, as shown below:
class Cello : IPen
{
string IPen.Color { get; set; }
private bool isOpen = false;
bool IPen.Close()
{
isOpen = false;
Console.WriteLine("Cello closed for writing!");
return isOpen;
}
bool IPen.Open()
{
isOpen = true;
Console.WriteLine("Cello open for writing!");
return isOpen;
}
void IPen.Write(string text)
{
//write text if open
if(isOpen)
Console.WriteLine("Cello: " + text);
}
}
In the above example of explicit implementation, notice that it cannot use access modifier 'public' explicitly. C# will give an error if you use 'public' modifier when implementing interface explicitly.
There can be multiple classes or structs that implements the same interface. Consider the following example.
class Parker : IPen
{
public string Color { get; set; }
private bool canWrite = false;
public bool Close()
{
canWrite = false;
Console.WriteLine("Parker is closed now!");
return canWrite;
}
public bool Open()
{
canWrite = true;
Console.WriteLine("Parker is open now!");
return canWrite;
}
public void Write(string text)
{
//write text if open
if(canWrite)
Console.WriteLine("Parker: " + text);
}
}
As you can see, the Parker
class implements the IPen
class. It implements the same functionalities declared in IPen
class but in a different way than Cello
class. (prints different messages in Open(), Close() and Write() methods.) Thus, multiple classes or Structs can implement the same interface which performs the same action but differently.
You can now create objects of the class and assigned to a variable of interface type.
IPen pen1 = new Cello();
IPen pen2 = new Parker();
The same variable can be used to instantiate all the classes which implemented IPen
interface.
IPen mypen = new Cello();
mypen = new Parker(); // assign Parker object to same variable
Implement Multiple Interfaces
A class or struct can implement multiple interfaces and must define all the members of all interfaces.
interface IBrandedPen
{
string GetBrandName();
}
class Parker : IPen, IBrandedPen
{
//Implement all members of IPen and IBrandedPen
}
Now, the Parker
class can be instantiated and assigned to either IPen
or IBrandedPen
interface, as shown below.
IPen pen1 = new Parker();
pen1.Open();// valid
pen1.GetBrandName(); //Compile-time error. Cannot call IBrandedPen method on the object of type IPen
IBrandedPen pen2 = new Parker();
pen2.GetBrandName();// valid
pen2.Open();//Compile-time error. Cannot call IPen method on the object of type IBrandedPen
As you can see, an object only supports methods of an interface to which it assigned to, e.g. pen1
assigned to IPen
so only supports methods of IPen
and not of IBrandedPen
.
An interface can also inherit one or more interface.
interface IPen
{
string Color { get; set; }
bool Open();
bool Close();
void Write(string text);
}
interface IBrandedPen : IPen
{
string GetBrandName();
}
class Parker : IBrandedPen
{
//Implement all members of IPen and IBrandedPen
}
- An interface only contains declarations of method, properties, indexers, and events.
- An interface can be implement implicitly or explicitly by a class or struct.
- A class or struct which implements an interface, must use 'public' access modifier.
- An interface cannot include private, protected, or internal members. All the members are public by default.
- Do not include 'public' in an interface as all the members are public by default. C# will give compile-time error if used 'public'.
- Implement interface explicitly using
InterfaceName.
with all the members. - An interface can inherit one or more interfaces.