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);
}
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);
}
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;
}
}
✔️ 3. When you’re defining capabilities
Examples:
IDisposableIEnumerableIComparable
✔️ 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();
}
✔️ 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);
}
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();
}
Scenario 3: Logging Framework
You want multiple loggers (FileLogger, DbLogger, CloudLogger).
Use an interface:
public interface ILogger
{
void Log(string message);
}
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();
}
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)