← Back

SOLID in C#

2026-01-06 22:54 · 👁 33255

#c#

🚀 SOLID in C# — Principles That Still Matter (With Real Examples)

SOLID is often taught as theory.
In real .NET systems, it’s a practical toolkit for writing code that survives growth.

Let’s go through each principle with concrete examples — no UML, no fluff.


🧩 S — Single Responsibility Principle (SRP)

A class should have one reason to change.

❌ Too many responsibilities:

public class OrderService
{
    public void CreateOrder(Order order) { }
    public void SaveToDatabase(Order order) { }
    public void SendEmail(Order order) { }
}

✅ Split responsibilities:

public class OrderService
{
    public void CreateOrder(Order order) { }
}

public class OrderRepository
{
    public void Save(Order order) { }
}

public class EmailNotifier
{
    public void Send(Order order) { }
}

🎯 Result: easier testing, clearer intent, safer changes.


🧩 O — Open/Closed Principle (OCP)

Open for extension, closed for modification.

❌ Changing logic every time:

if (type == "Vip") discount = 0.2m;
else discount = 0.1m;

✅ Extend behavior instead:

public interface IDiscountPolicy
{
    decimal Apply(decimal total);
}

public class VipDiscount : IDiscountPolicy
{
    public decimal Apply(decimal total) => total * 0.8m;
}

🎯 Add new discounts without touching existing code.


🧩 L — Liskov Substitution Principle (LSP)

Derived types must be substitutable for their base types.

❌ Violating expectations:

public class ReadOnlyFile : File
{
    public override void Write(string text)
        => throw new NotSupportedException();
}

This breaks callers relying on File.

✅ Better design:

public interface IReadFile { string Read(); }
public interface IWriteFile { void Write(string text); }

🎯 If it throws “NotSupportedException”, it’s probably violating LSP.


🧩 I — Interface Segregation Principle (ISP)

Don’t force clients to depend on methods they don’t use.

❌ Fat interface:

public interface IMachine
{
    void Print();
    void Scan();
    void Fax();
}

✅ Segregated interfaces:

public interface IPrinter { void Print(); }
public interface IScanner { void Scan(); }

🎯 Smaller interfaces → fewer breaking changes.


🧩 D — Dependency Inversion Principle (DIP)

Depend on abstractions, not implementations.

❌ Hard dependency:

public class OrderService
{
    private readonly SqlOrderRepository _repo = new();
}

✅ Inverted dependency:

public class OrderService
{
    public OrderService(IOrderRepository repo)
    {
        _repo = repo;
    }
}

🎯 Enables testing, swapping implementations, and cleaner architecture.


🧠 SOLID in Modern .NET (Reality Check)

  • DI containers make D easy
  • Interfaces & records simplify O and I
  • Primary constructors reduce boilerplate
  • Lambdas often replace small strategy classes

SOLID adapts — it doesn’t disappear.


⚠️ Common SOLID Anti-Patterns

❌ One interface per class “just in case”
❌ Over-abstraction in CRUD apps
❌ SRP applied at method level only
❌ Complex inheritance trees
❌ SOLID used as dogma instead of guidance

If SOLID makes code harder to read, you’re overdoing it.


🎯 Final Takeaway

SOLID is not about rules.
It’s about controlling change.

Good SOLID code:

  • Changes in fewer places
  • Breaks less often
  • Is easier to test
  • Is easier to explain

Write code for the next developer — and that developer is usually future you.


#dotnet #csharp #solid #softwarearchitecture #cleancode #backend #engineering

Rejoining the server...

Rejoin failed... trying again in seconds.

Failed to rejoin.
Please retry or reload the page.

The session has been paused by the server.

Failed to resume the session.
Please reload the page.