Codectionary / Developer documentation / C#

Interfaces

An interface defines a contract of members that implementing classes must provide, without specifying how those members work internally. By convention, interface names start with a capital I (IShape, IComparable). Unlike a class, an interface cannot be instantiated directly. A class uses a colon to implement an interface, and a single class can implement multiple interfaces - C#'s way of achieving a form of multiple inheritance.

Read the syntax

An interface names operations a type promises to provide; a class lists interfaces after a colon and implements their required members. An interface reference can point to any conforming implementation.

A default interface method has a body and can be called through an interface reference. It does not automatically become an ordinary public member callable on the class reference.

Syntax

interface IInterfaceName {\n  returnType MethodName(parameters);\n}

Examples

Basic Interface

Defining a contract and implementing it in a class.

IShape rect = new Rectangle(5, 3);
Console.WriteLine(rect.Area());  // 15

public interface IShape
{
    double Area();
    double Perimeter();
}

public class Rectangle : IShape
{
    public double Width, Height;

    public Rectangle(double width, double height)
    {
        Width = width;
        Height = height;
    }

    public double Area() => Width * Height;
    public double Perimeter() => 2 * (Width + Height);
}
  1. Defining a contract and implementing it in a class.
  2. An interface names operations a type promises to provide; a class lists interfaces after a colon and implements their required members. An interface reference can point to any conforming implementation.
  3. Rectangle implements Area and Perimeter, so it satisfies IShape. The interface-typed rect calls Rectangle.Area and prints 15.

Implementing Multiple Interfaces

A class can implement more than one interface, gaining the contract of each.

Triathlete athlete = new Triathlete();
athlete.Swim();
athlete.Run();

public interface ISwimmer { void Swim(); }
public interface IRunner { void Run(); }

public class Triathlete : ISwimmer, IRunner
{
    public void Swim() => Console.WriteLine("Swimming");
    public void Run() => Console.WriteLine("Running");
}
  1. A class can implement more than one interface, gaining the contract of each.
  2. An interface names operations a type promises to provide; a class lists interfaces after a colon and implements their required members. An interface reference can point to any conforming implementation.
  3. Triathlete implements both interfaces and supplies both required methods. The two calls print Swimming and Running.

Default Interface Methods (C# 8+)

Modern C# lets interfaces provide a default implementation, which implementing classes can use as-is or override.

Car car = new Car();
car.Drive();
((IVehicle)car).Honk();  // uses the default implementation

public interface IVehicle
{
    void Drive();

    void Honk() => Console.WriteLine("Beep beep!");  // has a body
}

public class Car : IVehicle
{
    public void Drive() => Console.WriteLine("Driving a car");
}
  1. Modern C# lets interfaces provide a default implementation, which implementing classes can use as-is or override.
  2. An interface names operations a type promises to provide; a class lists interfaces after a colon and implements their required members. An interface reference can point to any conforming implementation.
  3. Car supplies Drive but uses the default interface implementation of Honk. The cast to IVehicle exposes that default method and prints Beep beep!.

Interface as a Type Reference

Using an interface as the declared type lets you write flexible code that works with any implementation.

void ProcessPayment(IPaymentMethod method, double amount) => method.Pay(amount);

ProcessPayment(new CreditCard(), 50.0);
ProcessPayment(new PayPal(), 30.0);

public interface IPaymentMethod
{
    void Pay(double amount);
}

public class CreditCard : IPaymentMethod
{
    public void Pay(double amount) => Console.WriteLine($"Paid ${amount} with credit card");
}

public class PayPal : IPaymentMethod
{
    public void Pay(double amount) => Console.WriteLine($"Paid ${amount} with PayPal");
}
  1. Using an interface as the declared type lets you write flexible code that works with any implementation.
  2. An interface names operations a type promises to provide; a class lists interfaces after a colon and implements their required members. An interface reference can point to any conforming implementation.
  3. ProcessPayment accepts either implementation through IPaymentMethod. It delegates each amount to the supplied class, printing one credit-card line and one PayPal line.

Best practices

  • Program to an interface rather than a concrete class (declare variables as IShape, not Rectangle) for more flexible, decoupled code
  • Prefix interface names with I (IShape, IRepository) following standard C# naming conventions
  • Keep interfaces small and focused (Interface Segregation Principle) - many specific interfaces beat one large, do-everything interface
  • Use default interface methods sparingly, mainly for adding new functionality to an interface without breaking existing implementing classes

Runtime & versions

.NET runtime. Feature availability depends on the language and runtime version used by your project; consult the official reference below.

C# language reference

Specifications & further reading