In this article, we are going to describe the types of inheritance in C# and their use in various scenarios.

To download the source code for this article, you can visit our GitHub repository.

Let’s dive in.

What is Inheritance in C#?

The inheritance is one of the main object-oriented programming paradigms, and it permits the reuse of the same code in more than one class. This way, instead of re-writing the same code in several places, we use inheritance to define a class based on another one already defined. We use a base class to create derived classes.

In this article, we will focus on different inheritance types. There are 3 types of inheritance in C#:

  • Single Inheritance
  • Multilevel Inheritance
  • Multiple Inheritance (with interfaces)

To get to the heart of the matter let’s define a base class:

public class MobileDevice
{
    public string OperatingSystem { get; set; } = null!;
    public double Inches { get; set; }
    public bool IsConnected { get; set; }

    public virtual bool DeviceCanMakePhoneCall()
    {
       return false;
    }
}

The MobileDevice is a class with three properties: OperatingSystem, Inchesand IsConnected. It implements the method DeviceCanMakePhoneCall() of returning false. The virtual keyword forces the override of this method in its derived classes.

Now, let’s dive into each type of inheritance in C# in more detail.

Single Inheritance

The simplest type of inheritance is the single inheritance

Let’s introduce a new Smartphone class:

public class Smartphone : MobileDevice
{
    public List<string> InstalledApps { get; private set; }

    public Smartphone() 
    {
        InstalledApps = new List<string>();
    }

    protected Smartphone(string operatingSystem)
    {
        OperatingSystem = operatingSystem;
        InstalledApps = new List<string>();
    }

    public override bool DeviceCanMakePhoneCall()
    {
        return true;
    }

    public virtual void GetDescription()
    {
        Console.WriteLine($"This smartphone is {Inches} inches big and its operating system is {OperatingSystem}");
    }

    public void ShowInstalledApps()
    {
        Console.WriteLine($"There are {InstalledApps.Count} app installed");
    }
}

Smartphone inherits from the base class MobileDevice and it overrides the method DeviceCanMakePhoneCall(), returning true.

We can define an instance of Smartphone class now:

var smartphone = new Smartphone()
{
    Inches = 5.5,
    OperatingSystem = "iOS"
};

We set Inches and OperatingSystem properties inherited from MobileDevice. The GetDescription() method has the virtual modifier which means all derived classes must override it. Moreover, we’ve added ShowInstalledApp(), that prints the number of installed apps. This method has just a public modifier. This means that any class inheriting from Smartphone will have the same implementation of this method.

If we call the smartphone.GetDescription() and smartphone.ShowInstalledApps() methods, we’ll get the values we’ve set for our Smartphone instance:

This smartphone is 5,5 inches big and its operating system is iOS
There are 0 app installed

Finally, the property InstalledApps represents a list of apps downloaded on the device. In fact, the derived class can have its own properties other than the ones it has inherited from the base class:

single inheritance in C#

 

Multilevel Inheritance

The multilevel inheritance permits deriving a class from another one already derived from a base class. For example, let’s declare the AndroidSmartphone:

public class AndroidSmartphone : Smartphone
{
    public AndroidSmartphone() : base(operatingSystem: "Android")
    {
    }

    public override void GetDescription()
    {
        Console.WriteLine($"This Android smarphone is {Inches} inches big, and {InstalledApps.Count} apps downloaded from Google Store");
    }

    public void DownloadAppFromStore(string app)
    {
        InstalledApps.Add(app);
        Console.WriteLine($"I downloaded {app} from Google Store");
    }
}

The AndroidSmartphone class inherits the properties from the Smartphone class but the value of the OperatingSystem property is always equal to “Android”. In fact, in this case, we fix it in the constructor, so when we define a new instance of AndroidSmartphone, we don’t need to set it manually.  

AndroidSmartphone overrides the GetDescription() method that was virtual in the Smartphone class. As with the properties, the derived classes can have unique methods like DownloadAppFromStore(string app).

To continue, let’s create an AndroidSmartphone instance and invoke the methods:

var androidSmartphone = new AndroidSmartphone()
{
    Inches = 4,
};

androidSmartphone.GetDescription();
androidSmartphone.DownloadAppFromStore("WhatsApp");
androidSmartphone.ShowInstalledApps();

Console.WriteLine(androidSmartphone.OperatingSystem);
Console.WriteLine(androidSmartphone is MobileDevice);

Since we are using multilevel inheritance, the androidSmartphone is MobileDevice statement prints out true:

This Android smarphone is 4 inches big, and 0 apps downloaded from Google Store
I downloaded WhatsApp from Google Store
There are 1 app installed
Android
True

Finally, the output of GetDescription() is different from the one implemented in Smartphone class, since we override it:

multilevel inheritance in C#

 

Multiple Inheritance

C# doesn’t have a concept of multiple inheritance exactly, which permits multiple classes to inherit from a single base class. 

To demonstrate how we can go around this problem, we’re going to create a ConvertibleNotebook class first:

public class ConvertibleNotebook : MobileDevice
{
    public int UsbPortNumbers { get; set; }

    public override bool DeviceCanMakePhoneCall()
    {
        if (IsConnected)
        {
            return true;
        }

        return false;
    }

    public void WriteWithKeyboard(string message)
    {
        Console.WriteLine(message);
    }
}

A ConvertibleNotebook inherits from MobileDevice all the properties and it overrides the DeviceCanMakePhoneCall(). Moreover, it has UsbPortNumber property, and the WriteWithKeyboard(string message) method that prints on the console a message passed as a parameter.  

Basically, Smartphone and ConvertibleNotebook classes have the common methods and properties defined by MobileDevice class, but they also have their own properties and methods that define them more specifically.

Let’s create an instance of ConvertibleNotebook class:

var convertibleNotebook = new ConvertibleNotebook()
{
    Inches = 11.6,
    OperatingSystem = "Windows 11",
    UsbPortNumbers = 3
};

convertibleNotebook.DeviceCanMakePhoneCall();
convertibleNotebook.WriteWithKeyboard("I can write with keyboard");

A ConvertibleNotebook inherits from MobileDevice the properties Inches and OperatingSystem and it also has the UsbPortNumbers property:

multiple inheritance in C#

 

C# doesn’t permit the inheritance from more than one base class. This is mainly because this would add too much complexity, without too much benefit. (see the diamond problem for more information)

Let’s consider ConvertibleNotebook. Since it already inherits the MobileDevice class, it can not inherit another class. Inheriting from another class results in a compiler error “Class {DerivedClassName} cannot have multiple base classes ‘{BaseClass1Name}’ and ‘{BaseClass2Name}’.

We can overcome this problem using an interface:

public interface ILaptop
{
    public int UsbPortNumbers { get; set; }
    public void WriteWithKeyboard(string message);
}

Now the ConvertibleNotebook class can inherit both from the MobileDevice class, and the ILaptop interface:

public class ConvertibleNotebook : MobileDevice, ILaptop
{
    public int UsbPortNumbers { get; set; }

    public override bool DeviceCanMakePhoneCall()
    {
        if (IsConnected)
        {
           return true;
        }
 
        return false;        
    }

    public void WriteWithKeyboard(string message)
    {
        Console.WriteLine(message);
    }
}

This way, ConvertibleNotebook implements ILaptop interface providing an implementation of WriteWithKeyboard(string message), but it also inherits from MobileDevice class overriding DeviceCanMakeCall().

interface inheritance in C#

 

How to Prevent Inheritance in C#

We know that not all methods (or properties) of a class should be visible in the derived classes. To do so, for the overridden methods, like GetDescription() in the AndroidSmartphone class, we need to use the sealed keyword:

public override sealed void GetDescription()
{
    Console.WriteLine($"This Android smarphone is {Inches} inches big, and {InstalledApps.Count} apps downloaded from Google Store");
}

This way, any other derived class will not be able to inherit this method. When we deal with property or with a not-overridden method, instead, we need to use the private modifier. For example, we can modify in the Smartphone class:

private void ShowInstalledApps()
{
    Console.WriteLine($"There are {InstalledApps.Count} app installed");
}

In this case, if we try to invoke it on AndroidSmarphone instance, we will have a compilation error. In factShowInstalledApps() is private in Smartphone class and not visible in AndroidSmartphone:

androidSmartphone.ShowInstalledApps(); //Error CS0122 'Smartphone.ShowInstalledApps()' is inaccessible due to its protection level

We can also make the entire class sealed as well.

Conclusions

In this article, we covered the different types of inheritance in C# and we’ve shown how we can use it or prevent it in our applications.