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
