SOLID Principles in C#
Apply SOLID by separating responsibilities and programming against abstractions so behavior can change without rewriting stable business logic.
Part 1: What You Will Learn
Apply SOLID by separating responsibilities and programming against abstractions so behavior can change without rewriting stable business logic.
- See Single Responsibility by keeping pricing policy separate from checkout orchestration.
- Apply Open/Closed by adding new discount policies through new classes.
- Use small interfaces that support Interface Segregation.
- Use Dependency Inversion by injecting an abstraction into the high-level service.
Project setup: Create a .NET 10 Console App. The example focuses on SRP, OCP, and DIP, then relates the design to the remaining SOLID principles.
Part 2: Topic-Specific Working Example
The following example is written specifically for this lesson. Create the project described above, enter the code, run it, and then change some values to observe how the feature behaves.
public interface IDiscountPolicy
{
decimal Apply(decimal subtotal);
}
public sealed class RegularDiscount : IDiscountPolicy
{
public decimal Apply(decimal subtotal) => subtotal;
}
public sealed class VipDiscount : IDiscountPolicy
{
public decimal Apply(decimal subtotal) => subtotal * 0.90m;
}
public sealed class CheckoutService(IDiscountPolicy discountPolicy)
{
public decimal CalculateTotal(decimal subtotal, decimal taxRate)
{
decimal discounted = discountPolicy.Apply(subtotal);
decimal tax = discounted * taxRate;
return discounted + tax;
}
}
CheckoutService regularCheckout =
new(new RegularDiscount());
CheckoutService vipCheckout =
new(new VipDiscount());
Console.WriteLine(regularCheckout.CalculateTotal(500m, 0.06m));
Console.WriteLine(vipCheckout.CalculateTotal(500m, 0.06m));Part 3: How the Code Works
- SRP: discount calculation belongs to discount-policy classes rather than the checkout workflow.
- OCP: a StudentDiscount class can be added without modifying CheckoutService.
- LSP: every IDiscountPolicy implementation can be substituted where the interface is expected without breaking the contract.
- ISP: the interface exposes only the one operation a discount policy needs.
- DIP: CheckoutService depends on IDiscountPolicy, an abstraction, rather than a concrete discount class.
Part 4: Mini Project & Practice
Mini project: add `MemberDiscount` and `FestivalDiscount` classes. Then write a test proving CheckoutService works with a fake IDiscountPolicy.
Tip: Type the code yourself in Visual Studio 2026, run it, then deliberately change one part at a time. The goal is to understand the feature rather than simply copy the finished example.
When you are comfortable with this lesson, continue to Lesson 26.
C# in Visual Studio 2026
📘 This lesson is part of the book C# in Visual Studio 2026 by Dr. Liew Voon Kiong.
View on Amazon Kindle Edition