Introduction
In C#, both abstract classes and interfaces are used to achieve abstraction — i.e., hiding implementation details and exposing only what’s necessary.
However, they serve different purposes in application design.
You’ll commonly use them in real-world projects such as:
Designing layered architecture (e.g., repository pattern)
Creating base templates for employee or user roles
Implementing multiple features (logging, notification, etc.)
Let’s explore their differences step-by-step with a Windows Forms real-time example.
1. Abstract Class – Definition
An abstract class is a class that cannot be instantiated directly.
It can contain:
Abstract methods (no body)
Non-abstract methods (with implementation)
Fields, constructors, and properties
It provides a base structure for derived classes.
Example
public abstract class Employee
{
public string Name { get; set; }
public double Salary { get; set; }
public abstract double CalculateBonus();
public void ShowDetails()
{
Console.WriteLine($"Employee: {Name}, Salary: {Salary}");
}
}
Here, Employee defines a template, and child classes (like Manager or Developer) must implement the CalculateBonus() method.
2. Interface – Definition
An interface defines a contract that classes must follow.
It can only contain:
Method signatures
Properties
Events
Indexers
It cannot contain any implementation or fields (until C# 8, where default implementations are allowed).
Example
public interface IReportGenerator
{
void GenerateReport();
}
Any class that implements this interface must define the GenerateReport() method.
3. Key Differences Between Abstract Class and Interface
| Feature | Abstract Class | Interface |
|---|
| Inheritance | Supports single inheritance | Supports multiple interfaces |
| Members | Can have both implemented and abstract members | Only method declarations |
| Access Modifiers | Can use public, protected, etc. | All members are public by default |
| Constructors | Can have constructors | Cannot have constructors |
| Fields | Can have fields | Cannot have fields |
| Use Case | When classes share common functionality | When classes share common behavior only |
4. Real-Time Example in Windows Forms
Let’s create a Windows Forms App to demonstrate Abstract Class and Interface in action.
We’ll simulate an Employee Management System, where each employee type calculates a different bonus and can generate reports.
Step 1: Create an Interface and an Abstract Class
public interface IReportGenerator
{
void GenerateReport();
}
public abstract class Employee
{
public string Name { get; set; }
public double Salary { get; set; }
public Employee(string name, double salary)
{
Name = name;
Salary = salary;
}
public abstract double CalculateBonus();
}
Step 2: Create Derived Classes
public class Manager : Employee, IReportGenerator
{
public Manager(string name, double salary) : base(name, salary) { }
public override double CalculateBonus()
{
return Salary * 0.20; // 20% bonus
}
public void GenerateReport()
{
MessageBox.Show($"Manager Report: {Name} earned bonus ₹{CalculateBonus()}");
}
}
public class Developer : Employee, IReportGenerator
{
public Developer(string name, double salary) : base(name, salary) { }
public override double CalculateBonus()
{
return Salary * 0.10; // 10% bonus
}
public void GenerateReport()
{
MessageBox.Show($"Developer Report: {Name} earned bonus ₹{CalculateBonus()}");
}
}
Step 3: Design the Windows Form
Form Controls (Form1):
Step 4: Code Behind (Form1.cs)
using System;
using System.Windows.Forms;
namespace WinFormsDemo
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
cmbRole.Items.Add("Manager");
cmbRole.Items.Add("Developer");
}
private void btnShow_Click(object sender, EventArgs e)
{
string role = cmbRole.Text;
string name = txtName.Text;
double salary;
if (!double.TryParse(txtSalary.Text, out salary))
{
MessageBox.Show("Please enter a valid salary amount.");
return;
}
Employee emp = null;
if (role == "Manager")
emp = new Manager(name, salary);
else if (role == "Developer")
emp = new Developer(name, salary);
else
{
MessageBox.Show("Please select a valid role.");
return;
}
// Polymorphism – calling overridden method
double bonus = emp.CalculateBonus();
lblResult.Text = $"{emp.Name} ({role}) gets bonus ₹{bonus}";
// Interface usage – Generate report
IReportGenerator report = (IReportGenerator)emp;
report.GenerateReport();
}
}
}
Output Example
| Input | Output |
|---|
| Role: Manager, Salary: 60000 | Manager Report: earns bonus ₹12000 |
| Role: Developer, Salary: 50000 | Developer Report: earns bonus ₹5000 |
5. Real-Time Use Cases
| Scenario | Abstract Class Use | Interface Use |
|---|
| Employee system | Define base properties (name, salary) | Common reporting or audit behavior |
| Payment gateway | Base Payment class (Card, UPI) | IPayment interface for multiple payment methods |
| E-commerce order | Base Order class | ITrackable for delivery tracking |
| Logging system | AbstractLogger class | ILogger interface for writing to file, DB, API |
Key Takeaways
Use an Abstract Class when you have shared code and state among subclasses.
Use an Interface when you only want to enforce a behavior or contract.
You can implement multiple interfaces, but inherit only one abstract class.
Combine both for a scalable and flexible architecture.
Conclusion
Abstract classes and interfaces are essential pillars of object-oriented design in C#.
In Windows Forms and ASP.NET, they help separate business logic from UI, ensure reusability, and make your application extensible for future modules.