Menu

C# Abstract Class: Abstract Methods, Examples and vs Interface

What an abstract class is in C#: a base class that cannot be instantiated and can declare abstract members its derived classes must implement. Covers abstract methods and properties, constructors, the template method pattern, and when to choose an interface instead.

This page includes runnable editors - edit, run, and see output instantly.

An abstract class is a class that exists only to be derived from. It cannot be instantiated, and it can declare abstract members: methods and properties with no body that every concrete derived class must implement. Everything else about it is an ordinary class: it can have fields, constructors and fully implemented methods that derived classes inherit.

Declaring an abstract class

Mark the class abstract, and mark each member that derived classes must supply abstract, ending it with a semicolon instead of a body:

Output:

Circle: area 7.07, perimeter 9.42
Rectangle: area 10.00, perimeter 13.00

Describe is written once, in the base class, and calls Area and Perimeter, which do not exist in Shape at all. That is the point of an abstract member: the base class can rely on it, and the compiler guarantees every concrete shape provides it. A derived class that forgets one does not compile:

class Triangle : Shape
{
    public Triangle() : base("Triangle") { }
    public override double Area() => 6;
}
// error CS0534: 'Triangle' does not implement inherited abstract member 'Shape.Perimeter()'

The fix is to implement Perimeter, or to mark Triangle itself abstract if it is an intermediate base for further classes.

Rules for abstract members

  • An abstract member has no body and is implicitly virtual: derived classes implement it with override.
  • Only abstract classes may contain abstract members. Putting one in a normal class is a compile error.
  • Abstract members cannot be private (nobody could override them) or static in a class.
  • Methods, properties, indexers and events can be abstract. Fields and constructors cannot.
  • An abstract class does not have to contain any abstract member. Marking a class abstract alone just prevents instantiation, useful for a base class that only makes sense through its subclasses.

An abstract property declares which accessors the derived class must provide:

abstract class Plan
{
    public abstract decimal MonthlyPrice { get; }
    public abstract string Name { get; }
}

class ProPlan : Plan
{
    public override decimal MonthlyPrice => 12.99m;
    public override string Name => "Pro";
}

Constructors in abstract classes

An abstract class can have constructors. They cannot be called with new, but every derived constructor runs one through : base(...), so they are where shared state is initialized and validated. Declare them protected, which says exactly that: only derived classes can use this.

The template method pattern

The most common reason to write an abstract class is to fix the order of an algorithm in the base class and let derived classes fill in individual steps. The base method that runs the steps is not virtual, so no subclass can reorder or skip them.

Output:

item,qty,price
Coffee beans,2,11.50
Filter papers,1,3.20

| Item | Qty | Price |
| --- | --- | --- |
| Coffee beans | 2 | 11.50 |
| Filter papers | 1 | 3.20 |

Total: 26.20

Each row is a named tuple, and the output is built with a StringBuilder. Note the mix: Header and Row are abstract because every format must decide them, and Footer is virtual with an empty default because most formats need nothing there. The steps are protected, so outside code can only call Export. Framework classes use the same idea: Stream and TextWriter are abstract base classes whose many convenience methods are built on a few members a derived class supplies (Read and Write for a stream, Write(char) for a text writer).

Abstract class vs interface

Both let you write code against a type without knowing the concrete class. They differ in what they can contain and how many a class can have:

Abstract classInterface
A class can inherit or implementonemany
Instance fields (state)yesno
Constructorsyesno
Methods with a bodyyesyes, since C# 8 (default interface methods)
Static membersyesyes, since C# 8; static abstract members since C# 11
Access modifiers on membersanypublic by default; others allowed since C# 8
Structs can use itnoyes
Adding a member latersafe if it is not abstractbreaks implementers, unless it has a default body

Default interface methods (C# 8) narrowed the gap, but not the core difference:

public interface ILogger
{
    void Write(string message);
    void Error(string message) => Write("ERROR: " + message);   // default implementation: C# 8, .NET Core 3.0+
}

A default method still cannot touch instance fields, because the interface has none; it can only call other members of the interface.

A practical way to choose:

  • Interface when you describe a capability that unrelated types can have (IComparable<T>, IDisposable, IShippingProvider), when structs should be able to take part, or when a class needs several such roles. Most dependency injection code is written against interfaces for this reason.
  • Abstract class when the derived types are genuinely variations of one thing and share state or a fixed algorithm, like the exporters above.
  • Both is common: an interface for callers to depend on, and an abstract base class that implements it and saves implementers from rewriting the shared parts. The interfaces page covers the interface side in detail.

Common mistakes

  • Trying to instantiate the base class. new Shape(...) is CS0144. Instantiate a derived class.
  • Forgetting override on the implementation. Writing public double Area() in the derived class does not implement the abstract member; the compiler reports CS0534 for the missing implementation, plus a warning that the new method hides the inherited one.
  • A public constructor on an abstract class. Harmless but misleading. Use protected.
  • Abstract classes with no shared code. If the base class has only abstract members and no state, an interface says the same thing and does not use up the single base class slot.
  • Calling abstract members from the base constructor. The derived implementation runs before the derived constructor's body, so fields that body assigns are still 0 or null.

Frequently Asked Questions

What is an abstract class in C#?

A class marked abstract is meant only as a base class: you cannot create an instance of it with new (error CS0144). It can contain normal fields, constructors and methods, plus abstract members that have no body and must be implemented by every non-abstract derived class.

What is the difference between an abstract class and an interface in C#?

A class can derive from only one abstract class but implement many interfaces. An abstract class can hold state (instance fields), constructors and members of any access level, and is the natural place for shared implementation. An interface describes a capability with no instance state; since C# 8 it may include default method bodies, but it still cannot have instance fields or constructors.

What is the difference between abstract and virtual methods in C#?

A virtual method has a body that derived classes may override. An abstract method has no body and derived classes must override it, otherwise they are abstract themselves (error CS0534 for a concrete class). Abstract methods can only appear in abstract classes.

Can an abstract class have a constructor in C#?

Yes. It runs when a derived class is constructed, through : base(...), and typically initializes the shared fields. Declare it protected: a public constructor on an abstract class suggests callers can use it, and they cannot.

Why can't I create an instance of an abstract class?

Because it may have abstract members with no implementation: calling new Shape().Area() would have no code to run. The compiler reports CS0144 ("Cannot create an instance of the abstract type or interface"). Create an instance of a concrete derived class instead, and hold it in a variable of the abstract type if you like: Shape s = new Circle(2);.

Coddy programming languages illustration

Learn to code with Coddy

GET STARTED