Isaac.

C# Interfaces

Learn how to use interfaces to define contracts and enable polymorphism in C#.

By EMEPublished: February 20, 2025
csharpinterfacespolymorphismabstractioncontractsdotnet

A Simple Analogy

Think of a USB standard. Any device that implements USB can be plugged into any USB port. Interfaces in C# work the same way: they define a contract that classes agree to follow, enabling interchangeability.


What Are Interfaces?

Interfaces define a contract—a set of methods, properties, and events that implementing classes must provide. They enable loose coupling and polymorphism without inheritance.


Why Use Interfaces?

  • Define contracts: Classes agree to implement specific behavior
  • Loose coupling: Code depends on abstractions, not concrete types
  • Polymorphism: Treat different implementations the same way
  • Testability: Mock implementations for unit tests

Basic Syntax

public interface IRepository<T>
{
    Task<T> GetByIdAsync(int id);
    Task<List<T>> GetAllAsync();
    Task AddAsync(T entity);
}

public class UserRepository : IRepository<User>
{
    public async Task<User> GetByIdAsync(int id) => /* impl */;
    public async Task<List<User>> GetAllAsync() => /* impl */;
    public async Task AddAsync(User entity) => /* impl */;
}

Multiple Interfaces

public interface ILogger { void Log(string msg); }
public interface IValidator { bool Validate(object obj); }

public class UserService : ILogger, IValidator
{
    public void Log(string msg) { }
    public bool Validate(object obj) { }
}

Practical Example

public interface IPaymentProcessor
{
    Task<bool> ProcessAsync(Payment payment);
    bool IsAvailable();
}

public class CreditCardProcessor : IPaymentProcessor
{
    public async Task<bool> ProcessAsync(Payment payment)
    {
        // Credit card logic
        return true;
    }
    
    public bool IsAvailable() => true;
}

// Polymorphism in action
public class CheckoutService
{
    public async Task<bool> Checkout(IPaymentProcessor processor, Payment payment)
    {
        return await processor.ProcessAsync(payment);
    }
}

Interfaces vs. Abstract Classes

| Feature | Interface | Abstract Class | |---------|-----------|-----------------| | Implementation | None | Partial | | Inheritance | Multiple | Single | | Access modifiers | Public only | Any | | Use case | Contracts | Shared behavior |


Related Concepts to Explore

  • SOLID principles (Interface Segregation)
  • Dependency injection
  • Design patterns (Strategy, Adapter, Factory)
  • Abstract classes and inheritance

Summary

Interfaces define contracts that enable flexible, testable, loosely-coupled code. Use them to design systems where implementations can be swapped, mocked, or extended without changing dependent code.