DEV Community

Sardar Mudassar Ali Khan
Sardar Mudassar Ali Khan

Posted on

SOLID Principal Using C# Introduction with Complete Example

SOLID is an acronym for five design principles that help create maintainable and flexible software systems. Here's an example for each principle:

1. Single Responsibility Principle (SRP):

The SRP states that a class should have only one reason to change. In other words, a class should have a single responsibility.

public class Customer
{
    public string Name { get; set; }
    public string Email { get; set; }

    public void SendEmail(string message)
    {
        // Code to send an email
    }
}
Enter fullscreen mode Exit fullscreen mode

In this example, the Customer class has a single responsibility, which is to represent a customer. The email-sending functionality has been separated into a separate class.

2. Open/Closed Principle (OCP):

The OCP states that software entities should be open for extension but closed for modification. In other words, you should be able to add new functionality without modifying existing code.

public interface IShape
{
    double CalculateArea();
}

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

    public double CalculateArea()
    {
        return Math.PI * Math.Pow(Radius, 2);
    }
}

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

    public double CalculateArea()
    {
        return Width * Height;
    }
}
Enter fullscreen mode Exit fullscreen mode

In this example, the IShape interface defines a contract for calculating the area of a shape. The Circle and Rectangle classes implement this interface and provide their own implementation of the CalculateArea method. If we want to add a new shape, we can do so without modifying the existing code.

3. Liskov Substitution Principle (LSP):

The LSP states that objects of a superclass should be replaceable with objects of its subclasses without affecting the correctness of the program.

public class Animal
{
    public virtual void MakeSound()
    {
        Console.WriteLine("Animal is making a sound.");
    }
}

public class Dog : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Dog is barking.");
    }
}

public class Cat : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Cat is meowing.");
    }
}
Enter fullscreen mode Exit fullscreen mode

In this example, the Animal class is the superclass, and Dog and Cat are its subclasses. Both subclasses can be used interchangeably wherever an Animal object is expected.

4. Interface Segregation Principle (ISP):

The ISP states that clients should not be forced to depend on interfaces they do not use. In other words, interfaces should be specific to the needs of the clients.

public interface IOrder
{
    void ProcessOrder();
}

public interface IInvoice
{
    void GenerateInvoice();
}

public class OnlineOrder : IOrder
{
    public void ProcessOrder()
    {
        // Code to process an online order
    }
}

public class PointOfSaleOrder : IOrder, IInvoice
{
    public void ProcessOrder()
    {
        // Code to process a point-of-sale order
    }

    public void GenerateInvoice()
    {
        // Code to generate an invoice
    }
}
Enter fullscreen mode Exit fullscreen mode

In this example, we have two interfaces, IOrder and IInvoice. The OnlineOrder class only needs to implement the IOrder interface, while the PointOfSaleOrder class implements both IOrder and IInvoice interfaces
. Clients can depend on specific interfaces based on their needs.

5. Dependency Inversion Principle (DIP):

The DIP states that high-level modules should not depend on low-level modules. Both should depend on abstractions. In other words, dependencies should be defined through interfaces or abstract classes.

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

public class FileLogger : ILogger
{
    public void Log(string message)
    {
        // Code to log message to a file
    }
}

public class DatabaseLogger : ILogger
{
    public void Log(string message)
    {
        // Code to log message to a database
    }
}

public class CustomerService
{
    private readonly ILogger _logger;

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

    public void AddCustomer(string name)
    {
        // Code to add a customer
        _logger.Log("Customer added: " + name);
    }
}
Enter fullscreen mode Exit fullscreen mode

In this example, the CustomerService class depends on the ILogger interface rather than concrete logger implementations. The actual logger implementation is injected into the CustomerService class through constructor injection.
These examples demonstrate the SOLID principles in action using C#. Applying these principles can lead to more maintainable, flexible, and testable code.

Top comments (0)