Language: EN

csharp-interfaces

What are and how to use interfaces in C#

An interface in C# is a collection of definitions that a class or a struct can implement (such as methods, properties, events, or indexers).

Unlike classes, interfaces do not contain method implementations, they only define the members that must be implemented by the classes or structs that implement them.

Interfaces are fundamental in object-oriented programming because they allow defining functionalities and behaviors that can be implemented by different classes, and they promote maintainability and code reuse.

Interfaces in C#

The declaration of an interface is done using the interface keyword.

[modifier] interface InterfaceName
{
    // Method definitions
    dataType MethodName(parameters);

    // Property definitions
    dataType PropertyName { get; set; }
}
  • InterfaceName: Is the unique name given to the interface.
  • Modifier: Can be public or internal to define the access level of the interface.
  • dataType: Specifies the data type of the properties and methods.
  • MethodName, PropertyName: Are the unique identifiers for the methods, properties, and events respectively.
  • parameters: Are the variables used to pass information to the method when called.

Implementing Interfaces

To implement an interface in a class the colon syntax (:) is used followed by the interface name. The class must provide implementations for all the members defined in the interface.

Here is an example of how to define and implement an interface in C#:

public interface IDriveable
{
    string LicensePlate { get; set; }

    // Methods
    void Drive();
    void Brake();
}

public class Car : IDriveable
{
    // Property implementation    
    public string LicensePlate { get; set; }

    // Method implementations
    public void Drive()
    {
        Console.WriteLine("The car is moving.");
    }

    public void Brake()
    {
        Console.WriteLine("The car has stopped.");
    }
}

In this example:

  • An interface IVehicle is defined with a property (LicensePlate) and two methods (Drive and Brake).
  • The class Car implements the interface IVehicle and provides the implementation for all its properties and methods.

Polymorphism with Interfaces

One of the most important features of interfaces is their ability to support polymorphism. This allows an instance of a class that implements an interface to be treated as an instance of that interface.

Suppose we have another class that implements IDriveable called Bicycle

public class Bicycle : IDriveable
{
	// implementation
}

Now we can define a variable of type IDriveable, and assign variables of type Car or Bicycle.

IDriveable vehicle;

vehicle = new Car();
vehicle.Start(); // Output: The car has started.
vehicle.Stop();  // Output: The car has stopped.

vehicle = new Bicycle();
vehicle.Start(); // Output: The bicycle has started moving.
vehicle.Stop();  // Output: The bicycle has stopped.

Implementing Multiple Interfaces

C# does not support direct multiple inheritance (a class deriving from multiple base classes). However, a class can implement multiple interfaces, which provides a way to achieve behavior similar to multiple inheritance.

For example, in this example, the class Duck implements the interfaces IFlyable and ISwimmable.

public interface IFlyable
{
    void Fly();
}

public interface ISwimmable
{
    void Swim();
}

public class Duck : IFlyable, ISwimmable
{
    public void Fly()
    {
        Console.WriteLine("The duck is flying.");
    }

    public void Swim()
    {
        Console.WriteLine("The duck is swimming.");
    }
}

Explicit Implementation

C# allows explicit implementation of interface members. This is useful when a class implements multiple interfaces that may have methods with the same name, or when specific implementations are desired that are not directly accessible through the class.

In this example, the class Multifunctional implements the interfaces IPrintable and IScannable. But both interfaces declare a method Print(). We can explicitly declare the interfaces to resolve the naming conflict.

public interface IPrintable
{
    void Print();
}

public interface IScannable
{
    void Print();
}

public class Multifunctional : IPrintable, IScannable
{
    void IPrintable.Print()
    {
        Console.WriteLine("Printing...");
    }

    void IScannable.Print()
    {
        Console.WriteLine("Scanning...");
    }
}

// Usage
IPrintable printer = new Multifunctional();
printer.Print(); // Output: Printing...

IScannable scanner = new Multifunctional();
scanner.Print(); // Output: Scanning...

Practical Examples

Representation of an Electronic Device

This interface IPowerable defines the methods that an electronic device must have. The class Phone implements this interface:

public interface IPowerable
{
    // Methods
    void TurnOn();
    void TurnOff();
    void Restart();
}

public class Phone : IPowerable
{
    // Method implementations
    public void TurnOn()
    {
        Console.WriteLine("The phone is turning on.");
    }

    public void TurnOff()
    {
        Console.WriteLine("The phone is turning off.");
    }

    public void Restart()
    {
        Console.WriteLine("The phone is restarting.");
    }
}

Communication Behavior

This interface ICommunicator defines the methods that a communication device must have. The class Phone implements this interface while maintaining IPowerable.

public interface ICommunicator
{
    // Methods
    void Call(string number);
    void SendMessage(string number, string message);
}

public class Phone : ICommunicator, IPowerable
{
	// ... IPowerable code from the previous example ... //
	
    // ICommunicator method implementations
    public void Call(string number)
    {
        Console.WriteLine($"Calling number {number}.");
    }

    public void SendMessage(string number, string message)
    {
        Console.WriteLine($"Sending message to number {number}: {message}");
    }
}

Payment Behavior

This interface IPayments defines the methods that a payment system must have. The class ElectronicPayment implements this interface:

public interface IPayments
{
    // Methods
    void ProcessPayment(decimal amount);
    void RefundPayment(decimal amount);
}

public class ElectronicPayment : IPayments
{
    // Method implementations
    public void ProcessPayment(decimal amount)
    {
        Console.WriteLine($"Processing payment of {amount}.");
    }

    public void RefundPayment(decimal amount)
    {
        Console.WriteLine($"Refunding payment of {amount}.");
    }
}