Tool for HR, Hiring Managers, and the Leadership Team

SOLID Principles in C#

SOLID Principles are 5 Object-Oriented Design principles that help you write clean, maintainable, scalable, and testable code. These are very commonly asked in C# interviews.

SOLID =

  • S → Single Responsibility Principle

  • O → Open/Closed Principle

  • L → Liskov Substitution Principle

  • I → Interface Segregation Principle

  • D → Dependency Inversion Principle

Let's go one by one with simple C# examples (Interview-Friendly) 👇

1. S — Single Responsibility Principle (SRP)

Single Responsibility Principle

Definition:
A class should have only one reason to change.

❌ Bad Example (Multiple Responsibilities)

public class Invoice
{
    public void CalculateTotal() { }

    public void PrintInvoice() { }

    public void SaveToDatabase() { }
}

Problem:
This class is doing 3 things

  • Calculation

  • Printing

  • Database saving

If any of these changes → class must change.

✅ Good Example (SRP Followed)

public class Invoice
{
    public void CalculateTotal() { }
}

public class InvoicePrinter
{
    public void PrintInvoice() { }
}

public class InvoiceRepository
{
    public void SaveToDatabase() { }
}

Now each class has one responsibility 👍

2. O — Open/Closed Principle (OCP)

Open Closed Principle

Definition:
Software should be open for extension but closed for modification.

❌ Bad Example

public class Discount
{
    public double GetDiscount(string customerType)
    {
        if(customerType == "Regular")
            return 10;

        if(customerType == "Premium")
            return 20;

        return 0;
    }
}

Problem:
If new type added → must modify existing code ❌

✅ Good Example

public interface ICustomer
{
    double GetDiscount();
}

public class RegularCustomer : ICustomer
{
    public double GetDiscount() => 10;
}

public class PremiumCustomer : ICustomer
{
    public double GetDiscount() => 20;
}

Now you can add new customer without modifying existing code 👍

3. L — Liskov Substitution Principle (LSP)

Liskov Substitution Principle

Definition:
Derived class should be replaceable for base class without breaking functionality.

❌ Bad Example

public class Bird
{
    public virtual void Fly()
    {
        Console.WriteLine("Flying");
    }
}

public class Penguin : Bird
{
    public override void Fly()
    {
        throw new Exception("Penguin can't fly");
    }
}

Problem:
Penguin cannot substitute Bird ❌

✅ Good Example

public abstract class Bird
{
}

public interface IFlyable
{
    void Fly();
}

public class Sparrow : Bird, IFlyable
{
    public void Fly()
    {
        Console.WriteLine("Flying");
    }
}

public class Penguin : Bird
{
}

Now no violation 👍

4. I — Interface Segregation Principle (ISP)

Interface Segregation Principle

Definition:
Clients should not be forced to implement methods they don't use

❌ Bad Example

public interface IWorker
{
    void Work();
    void Eat();
}

public class Robot : IWorker
{
    public void Work() { }

    public void Eat()  // Robot doesn't eat
    {
        throw new Exception();
    }
}

✅ Good Example

public interface IWork
{
    void Work();
}

public interface IEat
{
    void Eat();
}

public class Human : IWork, IEat
{
    public void Work() { }
    public void Eat() { }
}

public class Robot : IWork
{
    public void Work() { }
}

Clean and flexible 👍

5. D — Dependency Inversion Principle (DIP)

Dependency Inversion Principle

Definition:
Depend on abstractions, not concrete classes

❌ Bad Example

public class EmailService
{
    public void Send() { }
}

public class Notification
{
    private EmailService _email = new EmailService();

    public void Notify()
    {
        _email.Send();
    }
}

Problem:
Tightly coupled ❌

✅ Good Example

public interface IMessageService
{
    void Send();
}

public class EmailService : IMessageService
{
    public void Send() { }
}

public class SMSService : IMessageService
{
    public void Send() { }
}

public class Notification
{
    private readonly IMessageService _message;

    public Notification(IMessageService message)
    {
        _message = message;
    }

    public void Notify()
    {
        _message.Send();
    }
}

Now easily extendable 👍

Interview One-Line Definitions (Very Important)

Principle One-Line Answer
SRP One class should have one responsibility
OCP Open for extension, closed for modification
LSP Child class must replace parent class safely
ISP Don't force classes to implement unused methods
DIP Depend on abstraction, not concrete classes

Real-World Example (Easy to Remember)

Principle Real Life Example
SRP HR handles hiring only
OCP Add new payment method without changing old code
LSP Car → ElectricCar should behave like Car
ISP Printer with only print vs print+scan
DIP Switch works with any bulb

Why SOLID is Important (Interview Answer)

  • Clean code

  • Maintainable code

  • Scalable system

  • Easy unit testing

  • Loose coupling

  • Better architecture