Recommended Free Tools
Use an abstract class when related types need shared state, constructors, or protected behavior. Use an interface when you want to describe a capability or contract that unrelated types can implement, or when a type needs to satisfy multiple contracts. In modern C#, interfaces can also provide default implementations, but they still cannot hold instance fields or declare constructors.
What is the difference between an abstract class and an interface in C#?
An abstract class is a base class that can combine shared implementation with members that derived classes must supply. An interface defines a contract or capability that classes, records, and structs can implement. As Microsoft puts it, “An interface defines a contract” (Microsoft Learn: interface keyword).
As an Amazon Associate I earn from qualifying purchases.
| Decision point | Abstract class | Interface |
|---|---|---|
| Typical role | Shared foundation for related types | Contract or capability, including across unrelated types |
| Instance state | Can declare fields and provide shared implementation | Cannot declare instance fields; a property declaration alone does not create stored state |
| Constructors | Can declare constructors for derived types | Cannot declare constructors |
| Inheritance | A class can have only one direct base class | A class or struct can implement multiple interfaces; an interface can inherit multiple interfaces |
| Implementation | Can contain concrete, virtual, and abstract members | Can contain member declarations and, in modern C#, default implementations |
Both can help structure behavior, but they impose different relationships: an abstract base establishes a class inheritance relationship, while an interface lets a type promise a capability without sharing a base-class family. Microsoft recommends abstract classes for related types that share state, constructors, or non-public members, and interfaces for contracts that cut across unrelated hierarchies or when multiple contracts are needed (Microsoft Learn: inheritance; Microsoft Learn: .NET compatibility).
When should you choose an abstract class?
Choose an abstract class when the derived types are genuinely part of one family and should inherit common implementation or rules. It can hold instance data, initialize that data in a constructor, and expose protected or other non-public helpers to subclasses.
#1 Best Overall
- Use it to centralize state or setup that every derived type needs.
- Use abstract members when each concrete subtype must provide a particular operation.
- Use concrete or virtual members when subclasses should inherit behavior, with optional overriding where appropriate.
An abstract class cannot be instantiated directly. A non-abstract derived class must implement inherited abstract members. An abstract class may also have no abstract members at all; it can still serve as a non-instantiable shared base (Microsoft Learn: inheritance).
When should you choose an interface?
Choose an interface to describe what a type can do, especially when implementers may come from different class hierarchies or already need another base class. A class or struct can implement several interfaces, so interfaces work well for independent capabilities that can be combined. Microsoft describes interfaces as capabilities for classes that do not necessarily have an “is a” relationship (Microsoft Learn: inheritance).
Rank #2
- Use an interface for a capability such as compression, serialization, or disposal that multiple unrelated types may provide.
- Use multiple interfaces when a type must meet several independent contracts.
- Remember that interface properties without implementation declare required members; they do not create hidden auto-property storage.
Interface members can be explicitly implemented. In that case, callers generally access them through a variable typed as the interface rather than directly through the class instance (Microsoft Learn: interface keyword).
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Can an interface have a method body in C#?
Yes. Since C# 8.0, an interface can provide a default implementation for a member. Before C# 8.0, interface members could not contain implementations. Default interface methods let library authors add members with fallback behavior that existing implementers can use or override (Microsoft Learn: default interface methods).
This does not make an interface equivalent to an abstract class. Interfaces still cannot declare instance fields or constructors. C# also supports static abstract or virtual interface members, but these do not provide instance storage.
Check runtime and consumer compatibility
Default interface members are not universally frictionless for public APIs. Microsoft’s compatibility guidance says support can raise the minimum runtime requirement to .NET Core 3.0 or later; some languages do not support default interface members, and runtime dispatch can be ambiguous in some cases. A ref struct implementer must explicitly implement every instance interface member and cannot rely on default implementations (Microsoft Learn: .NET compatibility).
Rank #4
Before adding a default member to a public interface, check the target runtimes and the languages used by downstream consumers. A default body can ease interface evolution, but it does not remove compatibility decisions.
How can you use both in one design?
A type may derive from one abstract base class and implement one or more interfaces. The base class can hold family-wide state and required behavior, while interfaces identify additional capabilities.
Best Value
public abstract class StorageDevice
{
protected StorageDevice(string name) => Name = name;
public string Name { get; }
public abstract void Save(ReadOnlySpan<byte> data);
}
public interface ICompressible
{
byte[] Compress(ReadOnlySpan<byte> data);
}
public sealed class ArchiveDevice : StorageDevice, ICompressible
{
public ArchiveDevice() : base("archive") { }
public override void Save(ReadOnlySpan<byte> data) { /* device-specific save */ }
public byte[] Compress(ReadOnlySpan<byte> data) => data.ToArray();
}
Here, StorageDevice supplies a name initialized through a constructor and requires each concrete storage device to implement Save. ICompressible marks a separate capability that another, unrelated type could also implement.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




