DEV Community

DIVAKAR UPADHYAY
DIVAKAR UPADHYAY

Posted on Originally published at devladder.pages.dev

O: Open/Closed Principle (SOLID Principles with Examples)

👉 Full lesson with practice questions on DevLadder (free, lesson 2 of 8 in the SOLID Principles with Examples course)

Software entities should be open for extension, closed for modification: add new behaviour by adding code, not by editing tested code.

// ❌ Every new customer type edits this method
public decimal Discount(string type, decimal amount) => type switch
{
    "Regular" => amount * 0.05m,
    "Gold" => amount * 0.10m,
    "Platinum" => amount * 0.15m,     // edit again next quarter...
    _ => 0
};

// ✅ New type = new class; existing code untouched (Strategy pattern)
public interface IDiscountRule { string Type { get; } decimal Apply(decimal amount); }
public class GoldDiscount : IDiscountRule { public string Type => "Gold"; public decimal Apply(decimal a) => a * 0.10m; }
public class PlatinumDiscount : IDiscountRule { public string Type => "Platinum"; public decimal Apply(decimal a) => a * 0.15m; }

public class DiscountService(IEnumerable<IDiscountRule> rules)
{
    public decimal Discount(string type, decimal amount) =>
        rules.FirstOrDefault(r => r.Type == type)?.Apply(amount) ?? 0;
}
// Program.cs
builder.Services.AddSingleton<IDiscountRule, GoldDiscount>();
builder.Services.AddSingleton<IDiscountRule, PlatinumDiscount>();
Enter fullscreen mode Exit fullscreen mode

ASP.NET Core itself is OCP: you extend the pipeline by adding middleware, filters and services, without editing the framework.

Interview questions on SOLID Principles with Examples

What are the SOLID principles? Explain each briefly.

  • Single Responsibility: one reason to change per class.
  • Open/Closed: extend behaviour by adding code, not modifying existing code.
  • Liskov Substitution: subclasses must work anywhere the base class works.
  • Interface Segregation: small client-specific interfaces instead of a fat one.
  • Dependency Inversion: high- and low-level modules depend on abstractions; inject dependencies.

Follow with one concrete example from your own project, e.g. "payment providers behind IPaymentGateway, registered in DI: that's OCP and DIP."

Give a real example of the Single Responsibility Principle.

An InvoiceService that calculates totals, writes to SQL and sends email has three reasons to change. Split it into InvoiceCalculator, IInvoiceRepository and IInvoiceSender, with a small workflow class orchestrating them. Now an SMTP-to-SendGrid change touches only the sender, and each part has focused unit tests.

How do you implement the Open/Closed Principle in C#?

Through abstractions and polymorphism: define an interface (IDiscountRule, IExportFormatter), implement each variant as its own class, and let the consumer receive IEnumerable<IDiscountRule> from DI. Adding a variant means a new class and registration; no existing, tested code changes. Other OCP tools: Strategy, Decorator, middleware, filters, events.


Read the full lesson with progress tracking and the rest of the course on DevLadder: free step-by-step tutorials and interview questions for developers.

Next in the course: L: Liskov Substitution Principle →

Top comments (0)