The five SOLID design principles in object-oriented programming are intended to improve the readability, flexibility, and maintainability of software systems. We'll go into great detail about each SOLID principle in this blog article, using.NET Core examples.

1. The principle of single responsibility (SRP)
According to the Single Responsibility Principle, a class should only have one duty or responsibility, or one cause to change.

As an illustration
Take into consideration the User class, which manages emailing people and storing user data in a database. Due to the class's various responsibilities, this violates the SRP.

Bad Example
public class User
{
    public void Save()
    {
        // Saving user to the database
    }

    public void SendEmail()
    {
        // Sending email to the user
    }
}


Good Example
public class User
{
    public void Save()
    {
        // Saving user to the database
    }
}

public class EmailService
{
    public void SendEmail(User user)
    {
        // Sending email to the user
    }
}


2. Open/Closed Principle (OCP)
The Open/Closed Principle states that software entities should be open for extension but closed for modification. This means that classes should be designed in a way that allows new functionality to be added without changing existing code.

Example
Consider a class Area Calculator that calculates the area of shapes. Initially, it only supports rectangles. To adhere to the OCP, we can refactor the code to allow adding new shapes without modifying the existing AreaCalculator class.

Bad Example
public class Rectangle
{
    public double Width { get; set; }
    public double Height { get; set; }
}

public class AreaCalculator
{
    public double CalculateArea(Rectangle[] shapes)
    {
        double area = 0;

        foreach (var shape in shapes)
        {
            area += shape.Width * shape.Height;
        }

        return area;
    }
}


Good Example

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

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

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

public class AreaCalculator
{
    public double CalculateArea(Shape[] shapes)
    {
        double area = 0;

        foreach (var shape in shapes)
        {
            area += shape.Area();
        }

        return area;
    }
}


3. Liskov Substitution Principle (LSP)
The Liskov Substitution Principle states that objects of a superclass should be replaceable with objects of its subclasses without affecting the correctness of the program.

Example
Consider a Rectangle class and a Square class where a Square inherits from Rectangle. Violating the LSP would mean that substituting a Square object for a Rectangle object could lead to unexpected behavior.

Bad Example
public class Rectangle
{
    public virtual double Width { get; set; }
    public virtual double Height { get; set; }
}

public class Square : Rectangle
{
    private double _side;

    public override double Width
    {
        get => _side;
        set
        {
            _side = value;
            Height = value;
        }
    }

    public override double Height
    {
        get => _side;
        set
        {
            _side = value;
            Width = value;
        }
    }
}

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

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

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

public class Square : Shape
{
    public double Side { get; set; }

    public override double Area()
    {
        return Side * Side;
    }
}


4. Interface Segregation Principle (ISP)

The Interface Segregation Principle states that clients should not be forced to depend on interfaces they don’t use. It emphasizes breaking interfaces into smaller, more specific ones.

Example
Consider an IWorker interface that contains both Work() and TakeBreak() methods. This forces all implementing classes to implement both methods, even if they don’t need them.

Bad Example
public interface IWorker
{
    void Work();
    void TakeBreak();
}

public class Programmer : IWorker
{
    public void Work()
    {
        // Programming tasks
    }

    public void TakeBreak()
    {
        // Taking a break
    }
}

Good Example
public interface IWorker
{
    void Work();
}

public interface IBreakable
{
    void TakeBreak();
}

public class Programmer : IWorker, IBreakable
{
    public void Work()
    {
        // Programming tasks
    }

    public void TakeBreak()
    {
        // Taking a break
    }
}


5. Dependency Inversion Principle (DIP)
The Dependency Inversion Principle states that high-level modules should not depend on low-level modules. Both should depend on abstractions. Abstractions should not depend on details. Details should depend on abstractions.

Example

Consider a UserManager class that directly depends on a Logger class. This creates a tight coupling between the two classes, making it difficult to change the logging implementation.

Bad Example
public class Logger
{
    public void Log(string message)
    {
        // Logging implementation
    }
}

public class UserManager
{
    private Logger _logger;

    public UserManager()
    {
        _logger = new Logger();
    }
}


Good Example
public interface ILogger
{
    void Log(string message);
}

public class Logger : ILogger
{
    public void Log(string message)
    {
        // Logging implementation
    }
}

public class UserManager
{
    private ILogger _logger;

    public UserManager(ILogger logger)
    {
        _logger = logger;
    }
}


Conclusion
You can produce software architectures that are more flexible, scalable, and maintainable by comprehending and implementing the SOLID principles in your.NET Core applications. Writing clear, modular, and testable code is made easier by following these guidelines, which eventually improves software quality and developer efficiency.

HostForLIFE ASP.NET Core 8.0.4 Hosting

European best, cheap and reliable ASP.NET hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.