SoFunction
Updated on 2025-03-01

Detailed explanation of the opening and closing principle in C# object-oriented programming

In object-oriented programming,SOLIDis the acronym of five design principles designed to make software design easier to understand, flexible and maintainable. These principles are a subset of many principles proposed by American software engineer and lecturer Robert Cecil Martin, first proposed in his 2000 paper, Design Principles and Design Patterns.

The SOLID principle includes:

  • SSingle-responsibility principle
  • OOpen-closed principle
  • LLiskov substitution principle
  • IInterface segregation principle
  • DDependency inversion principle

In this article, we will introduce the principles of opening and closing.

Opening and closing principle

In the realm of object-oriented programming,Opening and closing principle (open-closed principle, OCP) RegulationObjects (classes, modules, functions, etc.) in the software should be open to extensions and closed to modifications.”, which means that an entity allows its behavior to be changed without changing its source code. This feature is particularly valuable in productized environments where changing the source code requires code review, unit testing, and such processes to ensure the quality of product usage. Code following the principle of opening and closing does not change when extended, so these processes are not needed.

Specifically for a class, that is, it should be able to extend its behavior without modifying the class's own code.

C# Example

Let's review the previous articleSingle function principleThe AreaCalculator class mentioned in

class AreaCalculator
{
    private List<object> _shapes;

    public AreaCalculator(List<object> shapes)
    {
        _shapes = shapes;
    }

    /// <summary>
    /// Calculate the sum of areas of all shapes    /// </summary>
    /// <returns></returns>
    public double Sum()
    {
        List<double> areas = new List<double>();

        foreach (var item in _shapes)
        {
            if (item is Square s)
            {
                ((, 2));
            }
            else if (item is Circle c)
            {
                ( * (, 2));
            }
        }

        return ();
    }
}

For the above calculation method, consider such a scenario, the user wants to calculate the sum of areas of some other shapes, such as triangles, rectangles, pentagons, etc.... You will have to edit this class repeatedly to add moreif/elseBlock, this violates the principle of opening and closing.

improve

A better approach is to remove the logic that calculates the area of ​​each shape from the AreaCalculator class and add it to the class corresponding to each shape. We can define a withCalcAreaMethod interface IShape, then let each shape implement this interface.

Interface IShape:

interface IShape
{
    /// <summary>
    /// Calculate area    /// </summary>
    /// <returns></returns>
    double CalcArea();
}

Modified Square and Circle classes:

/// <summary>
/// square/// </summary>
class Square : IShape
{
    public Square(double length)
    {
        SideLength = length;
    }
    public double SideLength { get; init; }

    public double CalcArea()
    {
        return (SideLength, 2);
    }
}

/// <summary>
/// Circular/// </summary>
class Circle : IShape
{
    public Circle(double radius)
    {
        Radius = radius;
    }

    public double Radius { get; init; }

    public double CalcArea()
    {
        return  * (Radius, 2);
    }
}

The AreaCalculator class also needs to make some corresponding modifications:

class AreaCalculator
{
    private List<IShape> _shapes;

    public AreaCalculator(List<IShape> shapes)
    {
        _shapes = shapes;
    }

    /// <summary>
    /// Calculate the sum of areas    /// </summary>
    /// <returns></returns>
    public double Sum()
    {
        List<double> areas = new List<double>();

        foreach (var item in _shapes)
        {
            (());
        }

        return ();
    }
}

At this time, if we have a new shape that needs to be calculated, we can directly add a new class that implements the interface IShape without modifying the code of the AreaCalculator class, such as adding a rectangular class:

/// <summary>
/// rectangle/// </summary>
class Rectangle : IShape
{
    public Rectangle(double width, double height)
    {
        Width = width;
        Height = height;
    }

    public double Width { get; init; }
    public double Height { get; init; }

    public double CalcArea()
    {
        return Width * Height;
    }
}

The SumCalculatorOutputter class that handles the output format also does not need to be modified:

class SumCalculatorOutputter
{
    protected AreaCalculator _calculator;

    public SumCalculatorOutputter(AreaCalculator calculator)
    {
        _calculator = calculator;
    }

    public string String()
    {
        return $"Sum of the areas of provided shapes: {_calculator.Sum()}";
    }

    public string JSON()
    {
        var data = new { Sum = _calculator.Sum() };
        return (data);
    }
}

Then, we modifyMainLet’s test the code in the method:

static void Main(string[] args)
{
    var shapes = new List<IShape> {
            new Circle(2),
            new Square(5),
            new Rectangle(2,3)
    };

    var areaCalculator = new AreaCalculator(shapes);
    var outputer = new SumCalculatorOutputter(areaCalculator);
    (());
    (());
}

Run it and the output is:

{"Sum":43.56637061435917}
Sum of the areas of provided shapes: 43.56637061435917

Now, these categories designs follow the principle of single function and the principle of opening and closing.

Summarize

In this article, I introduced the SOLID principleOpening and closing principle(open-closed principle), and concisely interprets its meaning and implementation through C# code examples, I hope it will be helpful to you.

Reference documentation:

/community/conceptual_articles/s-o-l-i-d-the-first-five-principles-of-object-oriented-design

This is the end of this article about the examples of the opening and closing principles in C# object-oriented programming. For more related contents of the opening and closing principles of C#, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!