SOLID: Open/Closed Principle in C#

The Open/Closed Principle (OCP) is a software design principle that states that software entities (classes, modules, functions, etc.) should be open for extension but closed for modification. This means that the behavior of a software entity can be extended without modifying its source code. In other words, you can add new functionality to a software entity without changing its existing code.

The OCP is one of the SOLID principles of object-oriented design. It helps to create software that is easy to maintain, extend, and test.

To illustrate the OCP in C#, let's consider an example of a simple shape hierarchy. We have a base Shape class and two derived classes, Circle and Rectangle.

public abstract class Shape
{
    public abstract double Area();
}

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

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

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

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

Now, let's say we want to add a new shape, a Triangle. We can do this without modifying the existing Shape, Circle, or Rectangle classes. Instead, we can create a new Triangle class that derives from the Shape class.

public class Triangle : Shape
{
    public double Base { get; set; }
    public double Height { get; set; }

    public override double Area()
    {
        return 0.5 * Base * Height;
    }
}

Notice that we were able to add the new shape without modifying the existing Shape, Circle, or Rectangle classes. This is the Open/Closed Principle in action.

To demonstrate the benefits of the OCP, let's say we now want to add a new feature that allows us to calculate the perimeter of a shape. We can do this by adding a new method, Perimeter(), to the Shape class.

public abstract class Shape
{
    public abstract double Area();
    public abstract double Perimeter();
}

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

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

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

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

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

    public override double Perimeter()
    {
        return 2 * (Width + Height);
    }
}

public class Triangle : Shape
{
    public double Base { get; set; }
    public double Height { get; set; }
    public double A { get; set; }
    public double B { get; set; }
    public double C { get; set; }

    public override double Area()
    {
        return 0.5 * Base * Height;
    }

    public override double Perimeter()
    {
        return A + B + C;
    }
}

Again, notice that we were able to add the new feature without modifying the existing Shape, Circle, Rectangle, or Triangle classes. This is the power of the Open/Closed Principle.

In conclusion, the Open/Closed Principle is an important software design principle that promotes maintainability, extensibility, and testability. By following this principle, you can create software that is easy to modify and extend without introducing bugs or breaking existing functionality.