C# Inheritance

Understanding and implementing inheritance in C# for object-oriented programming.

Inheritance is a fundamental concept in object-oriented programming (OOP) that allows a new class to inherit properties and methods from an existing class. In C#, this mechanism is known as single inheritance, meaning a class can only inherit from one base class directly.

What is Inheritance?

Inheritance promotes code reusability and establishes a relationship between classes. The class that inherits is called the derived class (or child class), and the class from which it inherits is called the base class (or parent class).

Key Concepts

Syntax for Inheritance

In C#, you specify the base class after the derived class name, separated by a colon (:).


public class BaseClass
{
    public string BaseProperty { get; set; }
    public void BaseMethod()
    {
        Console.WriteLine("This is from the base class.");
    }
}

public class DerivedClass : BaseClass
{
    public string DerivedProperty { get; set; }
    public void DerivedMethod()
    {
        Console.WriteLine("This is from the derived class.");
    }
}
                

Accessing Base Class Members

A derived class can access the public and protected members of its base class. The new keyword can be used to hide members from the base class, but this is generally discouraged in favor of polymorphism.


public class Program
{
    public static void Main(string[] args)
    {
        DerivedClass obj = new DerivedClass();
        obj.BaseProperty = "Set from derived object";
        Console.WriteLine(obj.BaseProperty); // Output: Set from derived object
        obj.BaseMethod(); // Output: This is from the base class.

        obj.DerivedProperty = "Specific to derived";
        Console.WriteLine(obj.DerivedProperty); // Output: Specific to derived
        obj.DerivedMethod(); // Output: This is from the derived class.
    }
}
                

The base Keyword

The base keyword is used to explicitly call members (constructors, methods, properties) of the base class from within the derived class.

Using base with Constructors

It's common to call the base class constructor from the derived class constructor to ensure the base class is properly initialized.


public class Vehicle
{
    public string Model { get; }

    public Vehicle(string model)
    {
        this.Model = model;
        Console.WriteLine($"Vehicle constructor called with model: {model}");
    }
}

public class Car : Vehicle
{
    public int NumberOfDoors { get; }

    public Car(string model, int doors) : base(model) // Call base class constructor
    {
        this.NumberOfDoors = doors;
        Console.WriteLine($"Car constructor called with {doors} doors.");
    }
}

// Usage in Main:
// Car myCar = new Car("Sedan", 4);
// Output:
// Vehicle constructor called with model: Sedan
// Car constructor called with 4 doors.
                

Using base with Methods

You can override a method in the derived class and still call the base class implementation using base.MethodName().


public class Shape
{
    public virtual void Draw()
    {
        Console.WriteLine("Drawing a generic shape.");
    }
}

public class Circle : Shape
{
    public override void Draw()
    {
        base.Draw(); // Call the base class implementation first
        Console.WriteLine("Drawing a circle.");
    }
}

// Usage in Main:
// Circle myCircle = new Circle();
// myCircle.Draw();
// Output:
// Drawing a generic shape.
// Drawing a circle.
                

Note: For a method in the base class to be callable via override in the derived class, it must be declared as virtual, abstract, or override in the base class.

Benefits of Inheritance

Sealed Classes

You can prevent a class from being inherited by marking it as sealed.


public sealed class ImmutableData
{
    // ... class members
}

// The following would cause a compile-time error:
// public class AnotherClass : ImmutableData { ... }
                

Tip: Use sealed classes when you want to prevent inheritance, perhaps for security reasons or to ensure that the class's behavior cannot be altered by derived classes.

Inheritance vs. Composition

While inheritance models an 'is-a' relationship, composition models a 'has-a' relationship. Composition is often preferred over inheritance for building complex systems, as it leads to more flexible and loosely coupled designs.

Choose inheritance when the 'is-a' relationship is clear and makes logical sense. For other relationships, favor composition.