DEV Community

Libin Tom Baby
Libin Tom Baby

Posted on

Interface vs Abstract Class in C# — What’s the Difference and When Should You Use Each?

Interface vs Abstract Class in C#

Choosing between an interface and an abstract class is one of the most fundamental design decisions in C#. It affects flexibility, testability, extensibility, and how your system evolves over time.

This guide breaks down the differences with definitions, examples, real-world scenarios, and clear rules you can apply in interviews and production code.


What Is an Interface?

An interface defines a contract — a set of members a class must implement.

It contains no implementation (until default interface methods were introduced in C# 8).

Key characteristics

  • Supports multiple inheritance
  • Defines capabilities, not behavior
  • Ideal for loose coupling
  • Perfect for dependency injection
  • Members are public by default

Example

public interface IEmailService
{
    void Send(string to, string subject, string body);
}
Enter fullscreen mode Exit fullscreen mode

Any class implementing this interface must provide the Send method.


What Is an Abstract Class?

An abstract class is a partially implemented class.

It can contain:

  • Abstract members (no implementation)
  • Concrete members (with implementation)
  • Fields
  • Constructors
  • Access modifiers

Key characteristics

  • Cannot be instantiated
  • Supports single inheritance only
  • Allows shared logic
  • Ideal when you want a base class with common behavior

Example

public abstract class PaymentProcessor
{
    public void Log(string message)
    {
        Console.WriteLine(message);
    }

    public abstract void Process(decimal amount);
}
Enter fullscreen mode Exit fullscreen mode

Derived classes must implement Process, but they inherit Log.


Side‑by‑Side Comparison

Feature Interface Abstract Class
Multiple inheritance ✔️ Yes ❌ No
Can contain fields ❌ No ✔️ Yes
Can have constructors ❌ No ✔️ Yes
Can have implemented methods ✔️ (C# 8+) ✔️ Yes
Enforces a contract ✔️ Yes ✔️ Yes
Provides shared logic ❌ No ✔️ Yes
Best for DI ✔️ Yes ⚠️ Sometimes
Versioning flexibility ⚠️ Limited ✔️ Strong

When to Use an Interface

✔️ 1. When you need multiple inheritance

C# classes can implement many interfaces but inherit only one class.

✔️ 2. When you want loose coupling

Interfaces are the backbone of dependency injection.

public class OrderService
{
    private readonly IPaymentGateway _gateway;

    public OrderService(IPaymentGateway gateway)
    {
        _gateway = gateway;
    }
}
Enter fullscreen mode Exit fullscreen mode

✔️ 3. When you’re defining capabilities

Examples:

  • IDisposable
  • IEnumerable
  • IComparable

✔️ 4. When you’re designing plugin-style architectures

Interfaces allow swapping implementations without breaking the system.


When to Use an Abstract Class

✔️ 1. When you need shared logic

Abstract classes let you define common behavior.

public abstract class Animal
{
    public void Eat() => Console.WriteLine("Eating...");
    public abstract void MakeSound();
}
Enter fullscreen mode Exit fullscreen mode

✔️ 2. When you want to control inheritance

Abstract classes allow protected members, constructors, and internal logic.

✔️ 3. When you need default behavior

Interfaces can do this now (C# 8 default methods), but abstract classes still offer more power.

✔️ 4. When you want to avoid breaking changes

Adding a new method to an interface breaks all implementations.

Adding a method to an abstract class does not.


Real‑World Scenarios

Scenario 1: Payment Gateways

You want Stripe, PayPal, and Square implementations.

Use an interface:

public interface IPaymentGateway
{
    bool Charge(decimal amount);
}
Enter fullscreen mode Exit fullscreen mode

Why?

Because each provider behaves differently — no shared logic needed.


Scenario 2: Vehicles with Shared Behavior

All vehicles accelerate the same way, but braking differs.

Use an abstract class:

public abstract class Vehicle
{
    public void Accelerate() => Console.WriteLine("Accelerating...");
    public abstract void Brake();
}
Enter fullscreen mode Exit fullscreen mode

Scenario 3: Logging Framework

You want multiple loggers (FileLogger, DbLogger, CloudLogger).

Use an interface:

public interface ILogger
{
    void Log(string message);
}
Enter fullscreen mode Exit fullscreen mode

Loose coupling is essential here.


Scenario 4: Template Method Pattern

You want a base workflow with overridable steps.

Use an abstract class:

public abstract class ReportGenerator
{
    public void Generate()
    {
        FetchData();
        Format();
        Export();
    }

    protected abstract void FetchData();
    protected abstract void Format();
    protected abstract void Export();
}
Enter fullscreen mode Exit fullscreen mode

Interview‑Ready Summary

  • Use interfaces to define what something can do.
  • Use abstract classes to define what something is and share logic.
  • Interfaces = capabilities
  • Abstract classes = base behavior + structure
  • Interfaces support multiple inheritance
  • Abstract classes support shared implementation

Top comments (0)