SOLID principles in C# with short examples

 

1. S - Single Responsibility Principle (SRP)

Principle: A class should have only one reason to change.

csharp
// Bad: Mixing responsibilities
public class Invoice
{
    public void CalculateTotal() { /*...*/ }
    public void PrintInvoice() { /*...*/ } // Change if printing logic changes
    public void SaveToDatabase() { /*...*/ } // Change if database logic changes
}

// Good: Separate responsibilities
public class Invoice
{
    public void CalculateTotal() { /*...*/ }
}

public class InvoicePrinter
{
    public void Print(Invoice invoice) { /*...*/ }
}

public class InvoiceRepository
{
    public void Save(Invoice invoice) { /*...*/ }
}

2. O - Open/Closed Principle (OCP)

Principle: Open for extension, closed for modification.

csharp
// Bad: Modifying existing code for new shapes
public class AreaCalculator
{
    public double CalculateArea(object shape)
    {
        if (shape is Rectangle) { /* Calculate rectangle */ }
        else if (shape is Circle) { /* Calculate circle */ }
        // MODIFY when adding a new shape
    }
}

// Good: Extend without modifying existing code
public abstract class Shape
{
    public abstract double CalculateArea();
}

public class Rectangle : Shape
{
    public override double CalculateArea() { /* ... */ }
}

public class Circle : Shape
{
    public override double CalculateArea() { /* ... */ }
}
// New shapes extend Shape without changing AreaCalculator

3. L - Liskov Substitution Principle (LSP)

Principle: Subtypes must be substitutable for their base types.

csharp
// Bad: Square breaks behavior of Rectangle
public class Rectangle
{
    public virtual int Width { get; set; }
    public virtual int Height { get; set; }
}

public class Square : Rectangle
{
    public override int Width { set { base.Width = base.Height = value; } } // Violates LSP
}

// Good: Separate base class or interface
public abstract class Shape { /* ... */ }
public class Rectangle : Shape { /* ... */ }
public class Square : Shape { /* ... */ }

4. I - Interface Segregation Principle (ISP)

Principle: Clients shouldn’t depend on interfaces they don’t use.

csharp
// Bad: Monolithic interface
public interface IWorker
{
    void Work();
    void Eat(); // Not all workers need this
}

// Good: Split interfaces
public interface IWorkable
{
    void Work();
}

public interface IEatable
{
    void Eat();
}

public class Robot : IWorkable // Robot doesn't eat
{
    public void Work() { /* ... */ }
}

5. D - Dependency Inversion Principle (DIP)

Principle: Depend on abstractions, not concretions.

csharp
// Bad: Direct dependency on concrete class
public class WeatherApi
{
    public string GetWeather() => "Sunny";
}

public class WeatherReporter
{
    private WeatherApi _api = new WeatherApi(); // Tight coupling
    public string Report() => _api.GetWeather();
}

// Good: Depend on abstraction
public interface IWeatherProvider
{
    string GetWeather();
}

public class WeatherReporter
{
    private readonly IWeatherProvider _provider;
    public WeatherReporter(IWeatherProvider provider) // Dependency injection
    {
        _provider = provider;
    }
    public string Report() => _provider.GetWeather();
}

Interview Tips:

  1. SRP: "One class, one job."

  2. OCP: "Extend behavior without changing code."

  3. LSP: "Subclasses should enhance, not break, base class behavior."

  4. ISP: "Keep interfaces small and focused."

  5. DIP: "Use abstractions to decouple layers."

Comments

Popular posts from this blog

.NET Core Interview Questions and Answers for 10+ Years Experienced Professionals

What are SOLID Principles?

.NET Core Senior Interview Q&A