Writing code in C# isn’t just about making things work — it’s about doing it the right way, so your code stays clean, smart, and easy to manage. That’s where the SOLID principles in C# come in. These five simple design rules, introduced by Robert C. Martin (you might know him as Uncle Bob), help you build code that’s easier to test, maintain, and scale — especially as your project gets bigger and more complex.
Let’s understand each principle with easy-to-grasp, real-world C# examples.
What Does SOLID Stand For?
SOLID is an acronym made up of five key principles in object-oriented programming. Each letter represents a rule that helps you write cleaner, smarter, and more maintainable code — especially in languages like C#. Here’s what each letter stands for, explained in a simple way:
1.Single Responsibility in SOLID Principles (C# Example)
Every class should have one reason to change.
Let’s understand each of the SOLID principles in C# with easy-to-grasp, real-world examples. These examples are simple, yet they reflect real business scenarios that you likely deal with every day.
Bad Example:
public class Invoice
{
public void CalculateTotal() { }
public void PrintInvoice() { }
public void SaveToDatabase() { }
}
Good Example (Following SRP):
public class InvoiceCalculator
{
public void CalculateTotal() { }
}
public class InvoicePrinter
{
public void PrintInvoice() { }
}
public class InvoiceRepository
{
public void SaveToDatabase() { }
}
2.Open/Closed Principle Explained with C# Code
Classes should be open for extension but closed for modification.
A notification system is a good use case. Instead of modifying a class to add new notification types, extend it.
Example:
public interface INotification
{
void Send(string message);
}
public class EmailNotification : INotification
{
public void Send(string message) => Console.WriteLine($"Email: {message}");
}
public class SMSNotification : INotification
{
public void Send(string message) => Console.WriteLine($"SMS: {message}");
}
public class NotificationService
{
private readonly INotification _notification;
public NotificationService(INotification notification)
{
_notification = notification;
}
public void Notify(string message)
{
_notification.Send(message);
}
}
3.Liskov Substitution from SOLID Principles in C#
Subtypes must be substitutable for their base types.
Don’t break behavior by incorrectly inheriting. For example, don’t make penguins fly if they can’t!
Bad Example:
public class Bird
{
public virtual void Fly() { }
}
public class Penguin : Bird
{
public override void Fly() => throw new Exception("Penguins can't fly!");
}
Good Example (Fixing LSP):
public interface IBird { }
public interface IFlyingBird : IBird
{
void Fly();
}
public class Sparrow : IFlyingBird
{
public void Fly() => Console.WriteLine("Sparrow flying");
}
public class Penguin : IBird
{
public void Swim() => Console.WriteLine("Penguin swimming");
}
4.Interface Segregation Principle in C#
No class should be forced to implement methods it doesn’t use.
Break large interfaces into smaller, specific ones.
Bad Example:
public interface IMachine
{
void Print();
void Scan();
void Fax();
}
public class OldPrinter : IMachine
{
public void Print() { }
public void Scan() => throw new NotImplementedException();
public void Fax() => throw new NotImplementedException();
}
Good Example:
public interface IPrinter
{
void Print();
}
public interface IScanner
{
void Scan();
}
public class OldPrinter : IPrinter
{
public void Print() => Console.WriteLine("Printing...");
}
5.Understanding Dependency Inversion in C#
Depend on abstractions, not concrete classes.
Instead of hardcoding dependencies, inject them.
Bad Example:
public class EmailService
{
public void SendEmail(string message) { }
}
public class OrderProcessor
{
private EmailService _emailService = new EmailService();
public void ProcessOrder()
{
_emailService.SendEmail("Order confirmed");
}
}
Good Example:
public interface IMessageService
{
void SendMessage(string message);
}
public class EmailService : IMessageService
{
public void SendMessage(string message) => Console.WriteLine($"Email: {message}");
}
public class OrderProcessor
{
private readonly IMessageService _messageService;
public OrderProcessor(IMessageService messageService)
{
_messageService = messageService;
}
public void ProcessOrder()
{
_messageService.SendMessage("Order confirmed");
}
}
Final Thoughts
Using SOLID principles in C# isn’t just about writing fancy architecture — it’s about making your life as a developer easier. These principles help you write code that’s clean, easy to follow, and simple to update when things change (and they always do). Whether you’re coding solo or working with a team, SOLID makes your projects easier to manage and ready for whatever comes next.