Paramclasses Academy - Blog

Tutorials Details

←
Post 15 of 30
→

What is Inheritance in C# ? Examplain Types and Implementation

What is Inheritance in C# ?  Examplain Types and Implementation

October 26, 2026

Introduction

Inheritance is one of the fundamental concepts of Object-Oriented Programming (OOP) in C#. It allows one class to acquire accessible members from another class, helping developers reuse code, establish relationships between types, and create maintainable applications.

For example, an application may contain a general Person class with properties such as Name and Age. A Student class and an Employee class can reuse those common members by inheriting from Person, while adding their own specialized properties and methods.

Inheritance helps reduce duplicated code and represents an is-a relationship between types. However, it should be used when the derived type genuinely represents a specialized form of the base type.

In this tutorial, you will learn how inheritance works in C#, the different inheritance patterns, how constructors work with inheritance, how method overriding works, and how to implement inheritance in practical applications.

What You Will Learn

  • What inheritance is in C#

  • Base classes and derived classes

  • The syntax of inheritance

  • Single, multilevel, hierarchical, and multiple inheritance

  • Why C# does not support multiple inheritance of classes

  • Constructor execution in inheritance

  • Method overriding and the virtual, override, and base keywords

  • Abstract classes and inheritance

  • Access modifiers in inheritance

  • Practical examples and common mistakes

1. What Is Inheritance in C#?

Inheritance is an OOP mechanism in which a class derives from another class and can reuse its accessible members.

The class being inherited from is called the base class or parent class. The class that inherits from it is called the derived class or child class.

For example:

  • Person can be a base class.

  • Student can be a derived class.

  • Employee can also be a derived class.

Both Student and Employee can reuse common members from Person, while defining their own additional behavior.

Basic Inheritance Syntax

class BaseClass
{
    public void Display()
    {
        Console.WriteLine("Base class method");
    }
}

class DerivedClass : BaseClass
{
    public void Show()
    {
        Console.WriteLine("Derived class method");
    }
}

In C#, the colon (:) specifies the base class.

The derived class can access the inherited public Display() method and its own Show() method.

2. Simple Inheritance Example in C#

Let's create a Person class and derive a Student class from it.

using System;

class Person
{
    public string Name { get; set; }

    public void DisplayName()
    {
        Console.WriteLine($"Name: {Name}");
    }
}

class Student : Person
{
    public int RollNumber { get; set; }

    public void DisplayRollNumber()
    {
        Console.WriteLine($"Roll Number: {RollNumber}");
    }
}

class Program
{
    static void Main()
    {
        Student student = new Student
        {
            Name = "Rahul",
            RollNumber = 101
        };

        student.DisplayName();
        student.DisplayRollNumber();
    }
}

Output:

Name: Rahul
Roll Number: 101

How This Example Works

  • Person is the base class.

  • Student : Person declares that Student inherits from Person.

  • Name and DisplayName() are inherited by Student.

  • RollNumber and DisplayRollNumber() belong specifically to Student.

  • The Student object can access the inherited public members and its own public members.

This demonstrates code reuse through inheritance.

3. Base Class vs Derived Class

Base Class Derived Class
Provides common functionality. Extends or specializes existing functionality.
Is the type being inherited from. Is the type that inherits from another class.
Defines shared state and behavior. Can add new members and override eligible inherited methods.
Example: Person Example: Student

A derived class does not automatically gain access to every member of the base class. Access depends on the member's access modifier and the context in which it is used.

For example, a derived class cannot directly access a private field declared in its base class.

4. Types of Inheritance in C#

Inheritance is commonly described using several structural patterns.

Inheritance type Description Supported with C# classes?
Single inheritance One derived class inherits from one base class. Yes
Multilevel inheritance A class derives from another derived class. Yes
Hierarchical inheritance Multiple derived classes inherit from the same base class. Yes
Multiple inheritance of classes One class inherits from multiple classes. No
Hybrid inheritance A combination of inheritance patterns. Possible through supported class and interface combinations, but not multiple class inheritance

These patterns describe how types are related. They do not necessarily represent separate C# keywords.

5. Single Inheritance in C#

Single inheritance occurs when one derived class inherits from one base class.

using System;

class Animal
{
    public void Eat()
    {
        Console.WriteLine("The animal is eating.");
    }
}

class Dog : Animal
{
    public void Bark()
    {
        Console.WriteLine("The dog is barking.");
    }
}

class Program
{
    static void Main()
    {
        Dog dog = new Dog();

        dog.Eat();
        dog.Bark();
    }
}

Output:

The animal is eating.
The dog is barking.

The Dog class reuses the Eat() method inherited from Animal and defines its own Bark() method.

6. Multilevel Inheritance in C#

Multilevel inheritance occurs when a class inherits from a class that itself inherits from another class.

Consider this hierarchy:

Animal → Mammal → Dog

using System;

class Animal
{
    public void Eat()
    {
        Console.WriteLine("Eating...");
    }
}

class Mammal : Animal
{
    public void Walk()
    {
        Console.WriteLine("Walking...");
    }
}

class Dog : Mammal
{
    public void Bark()
    {
        Console.WriteLine("Barking...");
    }
}

class Program
{
    static void Main()
    {
        Dog dog = new Dog();

        dog.Eat();
        dog.Walk();
        dog.Bark();
    }
}

Output:

Eating...
Walking...
Barking...

The Dog class can access the public members declared in both Mammal and Animal, subject to normal accessibility rules.

Multilevel inheritance is useful when the relationships between types are clear and each level represents a meaningful specialization.

7. Hierarchical Inheritance in C#

Hierarchical inheritance occurs when multiple classes inherit from the same base class.

For example, both Student and Teacher can inherit from Person.

using System;

class Person
{
    public string Name { get; set; }

    public void Introduce()
    {
        Console.WriteLine($"Hello, my name is {Name}.");
    }
}

class Student : Person
{
    public void Study()
    {
        Console.WriteLine($"{Name} is studying.");
    }
}

class Teacher : Person
{
    public void Teach()
    {
        Console.WriteLine($"{Name} is teaching.");
    }
}

class Program
{
    static void Main()
    {
        Student student = new Student
        {
            Name = "Rahul"
        };

        Teacher teacher = new Teacher
        {
            Name = "Priya"
        };

        student.Introduce();
        student.Study();

        teacher.Introduce();
        teacher.Teach();
    }
}

Output:

Hello, my name is Rahul.
Rahul is studying.
Hello, my name is Priya.
Priya is teaching.

Both classes reuse Person.Introduce(), while each defines its own specialized behavior.

8. Why C# Does Not Support Multiple Inheritance of Classes

In C#, a class can inherit directly from only one base class.

The following code is invalid:

class A
{
}

class B
{
}

// Invalid C# syntax:
// class C : A, B
// {
// }

C# restricts a class to one direct base class to avoid complications that can arise when multiple base classes provide overlapping implementations or conflicting inherited state.

How Can C# Support Multiple Behaviors?

C# allows a class to implement multiple interfaces.

using System;

interface IPrintable
{
    void Print();
}

interface IScannable
{
    void Scan();
}

class MultiFunctionPrinter : IPrintable, IScannable
{
    public void Print()
    {
        Console.WriteLine("Printing document...");
    }

    public void Scan()
    {
        Console.WriteLine("Scanning document...");
    }
}

class Program
{
    static void Main()
    {
        MultiFunctionPrinter printer =
            new MultiFunctionPrinter();

        printer.Print();
        printer.Scan();
    }
}

Output:

Printing document...
Scanning document...

MultiFunctionPrinter implements two interfaces, so it provides both sets of required behaviors without inheriting from multiple classes.

Interfaces are useful when different types need to support the same capabilities but do not necessarily share a common class hierarchy.

9. The base Keyword in C#

The base keyword refers to the base-class portion of the current object. It is commonly used to:

  • Call a base-class constructor.

  • Invoke a base-class implementation of a method that has been overridden.

Example: Calling a Base-Class Method

using System;

class Animal
{
    public virtual void MakeSound()
    {
        Console.WriteLine("Animal makes a sound.");
    }
}

class Dog : Animal
{
    public override void MakeSound()
    {
        base.MakeSound();
        Console.WriteLine("Dog barks.");
    }
}

class Program
{
    static void Main()
    {
        Dog dog = new Dog();
        dog.MakeSound();
    }
}

Output:

Animal makes a sound.
Dog barks.

The Dog implementation calls base.MakeSound() before printing its own message.

This is useful when a derived class needs to extend rather than completely replace the base-class behavior.

10. Method Overriding with virtual and override

Inheritance becomes particularly powerful when combined with runtime polymorphism.

A base-class method marked virtual can be overridden by a derived class using override.

using System;

class Animal
{
    public virtual void MakeSound()
    {
        Console.WriteLine("The animal makes a sound.");
    }
}

class Dog : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("The dog barks.");
    }
}

class Cat : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("The cat meows.");
    }
}

class Program
{
    static void Main()
    {
        Animal animal1 = new Dog();
        Animal animal2 = new Cat();

        animal1.MakeSound();
        animal2.MakeSound();
    }
}

Output:

The dog barks.
The cat meows.

Why Does This Work?

Although the variables are declared using the Animal type, they refer to objects of types Dog and Cat.

Because MakeSound() is virtual and overridden, C# invokes the implementation corresponding to each object's runtime type.

This is called runtime polymorphism.

Important Keywords

  • virtual: Allows an eligible base-class method or property accessor to be overridden.

  • override: Supplies a new implementation of an inherited virtual or abstract member.

  • base: Allows access to the base-class implementation from the derived class.

Use these keywords when you want derived types to customize behavior while preserving a common interface.

11. Constructor Execution in Inheritance

Constructors are not inherited. When a derived object is created, its constructor must also account for the initialization required by the base class.

If the base class has a parameterless constructor, the derived constructor can use it implicitly. If the base class requires arguments and has no accessible parameterless constructor, the derived class must specify an appropriate base-constructor call.

using System;

class Person
{
    public string Name { get; }

    public Person(string name)
    {
        Name = name;
        Console.WriteLine("Person constructor executed.");
    }
}

class Student : Person
{
    public int RollNumber { get; }

    public Student(string name, int rollNumber)
        : base(name)
    {
        RollNumber = rollNumber;
        Console.WriteLine("Student constructor executed.");
    }
}

class Program
{
    static void Main()
    {
        Student student = new Student("Rahul", 101);

        Console.WriteLine(student.Name);
        Console.WriteLine(student.RollNumber);
    }
}

Output:

Person constructor executed.
Student constructor executed.
Rahul
101

The base-class constructor runs before the body of the derived-class constructor. This ensures that the inherited part of the object is initialized before the derived constructor performs its own initialization.

12. Access Modifiers and Inheritance

Access modifiers control where class members can be accessed.

Modifier Accessibility summary
public Accessible wherever the containing type and member are accessible.
private Accessible only within the containing type.
protected Accessible within the containing type and its derived types, subject to language rules.
internal Accessible within the same assembly.
protected internal Accessible within the same assembly or through derived-type access, subject to language rules.
private protected Accessible within the containing class and derived classes in the same assembly.

Example: Protected Members

using System;

class Person
{
    protected string Name { get; set; }

    public Person(string name)
    {
        Name = name;
    }
}

class Student : Person
{
    public Student(string name) : base(name)
    {
    }

    public void Display()
    {
        Console.WriteLine($"Student Name: {Name}");
    }
}

class Program
{
    static void Main()
    {
        Student student = new Student("Amit");
        student.Display();

        // This is not allowed from Program:
        // Console.WriteLine(student.Name);
    }
}

Output:

Student Name: Amit

The derived class can access the protected Name property. Code in Program cannot directly access that property through the student reference because it is not public.

13. Abstract Classes and Inheritance

An abstract class is designed to serve as a base class. It cannot be instantiated directly, but it can define shared implementation and declare abstract members that derived classes must implement.

using System;

abstract class Shape
{
    public abstract double CalculateArea();

    public void Display()
    {
        Console.WriteLine(
            $"Area: {CalculateArea():F2}");
    }
}

class Circle : Shape
{
    public double Radius { get; }

    public Circle(double radius)
    {
        if (radius < 0)
        {
            throw new ArgumentOutOfRangeException(
                nameof(radius));
        }

        Radius = radius;
    }

    public override double CalculateArea()
    {
        return Math.PI * Radius * Radius;
    }
}

class Rectangle : Shape
{
    public double Width { get; }
    public double Height { get; }

    public Rectangle(double width, double height)
    {
        if (width < 0 || height < 0)
        {
            throw new ArgumentOutOfRangeException(
                "Dimensions cannot be negative.");
        }

        Width = width;
        Height = height;
    }

    public override double CalculateArea()
    {
        return Width * Height;
    }
}

class Program
{
    static void Main()
    {
        Shape circle = new Circle(5);
        Shape rectangle = new Rectangle(4, 6);

        circle.Display();
        rectangle.Display();
    }
}

Output:

Area: 78.54
Area: 24.00

The abstract Shape class defines a common contract. Circle and Rectangle provide their own area calculations, while both reuse the Display() method.

This design is useful when several related classes share common behavior but require different implementations of particular operations.

14. Practical Project: Employee Management System

Let's create a small employee management example using inheritance.

The application will contain:

  • A base Employee class.

  • A FullTimeEmployee derived class.

  • A PartTimeEmployee derived class.

  • An overridden method to calculate the salary for each employee type.

using System;
using System.Collections.Generic;

abstract class Employee
{
    public int EmployeeId { get; }
    public string Name { get; }

    protected Employee(int employeeId, string name)
    {
        if (employeeId <= 0)
        {
            throw new ArgumentOutOfRangeException(
                nameof(employeeId));
        }

        if (string.IsNullOrWhiteSpace(name))
        {
            throw new ArgumentException(
                "Name is required.", nameof(name));
        }

        EmployeeId = employeeId;
        Name = name;
    }

    public abstract decimal CalculateSalary();

    public virtual void DisplayDetails()
    {
        Console.WriteLine($"ID: {EmployeeId}");
        Console.WriteLine($"Name: {Name}");
        Console.WriteLine($"Salary: {CalculateSalary():C}");
    }
}

class FullTimeEmployee : Employee
{
    public decimal MonthlySalary { get; }

    public FullTimeEmployee(
        int employeeId,
        string name,
        decimal monthlySalary)
        : base(employeeId, name)
    {
        if (monthlySalary < 0)
        {
            throw new ArgumentOutOfRangeException(
                nameof(monthlySalary));
        }

        MonthlySalary = monthlySalary;
    }

    public override decimal CalculateSalary()
    {
        return MonthlySalary;
    }
}

class PartTimeEmployee : Employee
{
    public decimal HourlyRate { get; }
    public int HoursWorked { get; }

    public PartTimeEmployee(
        int employeeId,
        string name,
        decimal hourlyRate,
        int hoursWorked)
        : base(employeeId, name)
    {
        if (hourlyRate < 0)
        {
            throw new ArgumentOutOfRangeException(
                nameof(hourlyRate));
        }

        if (hoursWorked < 0)
        {
            throw new ArgumentOutOfRangeException(
                nameof(hoursWorked));
        }

        HourlyRate = hourlyRate;
        HoursWorked = hoursWorked;
    }

    public override decimal CalculateSalary()
    {
        return HourlyRate * HoursWorked;
    }
}

class Program
{
    static void Main()
    {
        List<Employee> employees = new List<Employee>
        {
            new FullTimeEmployee(
                101, "Rahul", 50000m),

            new PartTimeEmployee(
                102, "Priya", 500m, 40)
        };

        foreach (Employee employee in employees)
        {
            employee.DisplayDetails();
            Console.WriteLine("------------------");
        }
    }
}

Example output (currency formatting depends on the system's culture):

ID: 101
Name: Rahul
Salary: ₹50,000.00
------------------
ID: 102
Name: Priya
Salary: ₹20,000.00
------------------

How the Project Works

  1. Employee defines common employee information and an abstract salary calculation.

  2. FullTimeEmployee stores a monthly salary and implements CalculateSalary().

  3. PartTimeEmployee calculates salary from hourly rate and hours worked.

  4. Both derived constructors call base(...) to initialize shared employee data.

  5. The List<Employee> stores both types through their common base class.

  6. Calling DisplayDetails() uses the salary implementation appropriate to each runtime object.

This example demonstrates inheritance, constructor chaining, abstract classes, method overriding, and polymorphism in a single practical program.

For a real payroll system, additional rules would be needed for overtime, taxes, currency handling, benefits, and salary periods.

15. Advantages of Inheritance in C#

Inheritance can provide several benefits when used appropriately.

Code Reusability

Common properties and methods can be defined once in a base class and reused by derived classes.

Extensibility

Derived classes can add specialized members without rewriting all shared functionality.

Polymorphism

Base-class references can work with objects of different derived types, allowing overridden methods to provide type-specific behavior.

Maintainability

Shared behavior can be managed in a common base class rather than duplicated across several related classes.

Clear Type Relationships

Inheritance can model genuine is-a relationships, such as a Dog being an Animal.

16. Disadvantages and Limitations of Inheritance

Inheritance is useful, but it is not always the best design choice.

  • Tight coupling: Changes to a base class can affect derived classes.

  • Rigid hierarchies: A deep inheritance structure can become difficult to understand and maintain.

  • Incorrect relationships: Inheriting only to reuse a method can produce an inaccurate model of the domain.

  • Limited class inheritance: A C# class can have only one direct base class.

  • Fragile base-class behavior: Derived classes may depend on implementation details that change over time.

When a class simply needs the functionality of another class without representing a genuine is-a relationship, composition may be a better alternative.

For example, a Car has an Engine; it is not an Engine. A Car can therefore contain an Engine object instead of inheriting from Engine.

17. Common Mistakes in Inheritance

Mistake 1: Trying to inherit from two classes

Incorrect:

// Invalid C# class inheritance:
// class C : A, B { }

A class can have only one direct base class. Implement multiple interfaces when a type needs to support multiple contracts.

Mistake 2: Forgetting override

If you intend to replace the implementation of an inherited virtual method, use override and ensure that the base member is eligible for overriding.

Mistake 3: Trying to access private base members

A derived class cannot directly access a private field or method declared in its base class. Use an appropriate public or protected member when derived classes need access.

Mistake 4: Forgetting the base constructor

If the base class has no accessible parameterless constructor, the derived class must call an accessible base constructor with the required arguments.

Mistake 5: Using inheritance only for code reuse

Do not create an inheritance relationship when the types do not represent a genuine is-a relationship. Consider composition or interfaces instead.

Mistake 6: Creating deep inheritance hierarchies

Too many levels can make behavior difficult to trace. Keep the hierarchy focused and easy to understand.

18. Best Practices for Inheritance in C#

  1. Use inheritance for genuine is-a relationships.

  2. Keep base classes focused on shared responsibilities.

  3. Prefer composition when a has-a relationship better describes the design.

  4. Use virtual and override when runtime polymorphism is needed.

  5. Use abstract members to define required behavior for derived classes.

  6. Choose access modifiers carefully to avoid exposing unnecessary implementation details.

  7. Validate constructor arguments and maintain valid object state.

  8. Avoid deep hierarchies that are difficult to understand.

  9. Use interfaces when unrelated types need to support a common capability.

  10. Test derived classes to ensure they preserve the expected behavior of their base classes.

19. Practice Exercises

Exercise 1: Animal Inheritance

Create an Animal base class with an Eat() method. Derive Dog and Cat classes and give each class its own behavior.

Exercise 2: Person and Student

Create a Person class with Name and Age. Derive a Student class with RollNumber and a method to display all details.

Exercise 3: Multilevel Inheritance

Create three classes: Vehicle, Car, and ElectricCar. Give each class one relevant property or method.

Exercise 4: Method Overriding

Create a Shape base class and derive Circle and Rectangle. Implement an overridden method that calculates each shape's area.

Exercise 5: Constructor Chaining

Create a base Employee class and a derived Manager class. Use base(...) to initialize the employee information.

Exercise 6: Interface Implementation

Create two interfaces, IPrintable and ISavable. Implement both interfaces in a class without using multiple class inheritance.

20. Knowledge Check: Quiz

1. What is inheritance in C#?

A. A loop structure
B. A mechanism for deriving a class from another class
C. A database query
D. A type of exception

2. Which symbol is used to declare class inheritance in C#?

A. ->
B. ::
C. :
D. =>

3. How many direct base classes can a C# class inherit from?

A. One
B. Two
C. Three
D. Unlimited

4. Which keyword is used to override an eligible virtual method?

A. static
B. override
C. private
D. new

5. Which keyword can invoke a base-class constructor?

A. this
B. virtual
C. base
D. using

6. What is hierarchical inheritance?

A. One class inherits from several base classes
B. Several derived classes inherit from the same base class
C. A class inherits from itself
D. A method calls another method

7. Which feature allows a class to implement multiple contracts?

A. Multiple class inheritance
B. Interfaces
C. Constructors only
D. Private fields

Answers: 1-B, 2-C, 3-A, 4-B, 5-C, 6-B, 7-B.

21. Frequently Asked Questions (FAQs)

Q1. What is inheritance in C#?

Inheritance is an OOP mechanism that lets a derived class reuse accessible members of a base class and add specialized behavior.

Q2. What are the main types of inheritance?

Common structural patterns include single, multilevel, hierarchical, and hybrid inheritance. Multiple inheritance of classes is not supported in C#, although a class can implement multiple interfaces.

Q3. Does C# support multiple inheritance?

C# does not allow a class to inherit directly from multiple classes. A class can implement multiple interfaces to support several contracts.

Q4. What is the difference between virtual and override?

virtual marks a base-class member as eligible for overriding. override supplies a new implementation in a derived class.

Q5. What is the purpose of base?

The base keyword lets a derived class invoke an accessible base-class constructor or call a base-class implementation of an overridable member.

Q6. Are constructors inherited in C#?

No. A derived class has its own constructors and can invoke a base-class constructor through a constructor initializer such as base(...).

Q7. Can a derived class access private members of its base class?

Not directly. Private members are accessible only within the type that declares them. A base class can expose controlled access through public or protected members.

Q8. What is the difference between inheritance and composition?

Inheritance models an is-a relationship. Composition models a has-a relationship, where one object contains or uses another object.

Q9. Can an abstract class be instantiated?

No. An abstract class cannot be instantiated directly, but concrete derived classes can inherit from it and implement its required abstract members.

Q10. When should I use inheritance?

Use inheritance when a derived type is genuinely a specialized form of the base type and the shared contract makes the design clearer. Otherwise, consider composition or interfaces.

Conclusion

Inheritance is a powerful feature of C# that helps developers reuse shared functionality, organize related classes, and support runtime polymorphism. By understanding base classes, derived classes, inheritance patterns, constructor chaining, and method overriding, you can create more structured and maintainable applications.

Use inheritance when the relationship between types is meaningful, keep base classes focused, and consider composition when one object simply needs to use another.

←
Post 15 of 30
→