Interview Q&A

Technical interview Q&A plus 100+ career & HR questions—notice period, salary negotiation, resume, LinkedIn, freelancing, AI careers, and behavioral interviews with detailed, real-world answers.

Popular tracks

Design Patterns & SOLID Design Patterns in C# · SOLID

The Singleton pattern ensures a class has only one instance and provides a global point of

ccess to it. It’s commonly used when exactly one object is needed to coordinate actions

cross the system, such as configuration settings, logging, or caching.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

One common thread-safe implementation uses lazy initialization with Lazy<T>:

public sealed class Singleton
{
private static readonly Lazy<Singleton> instance = new
Lazy<Singleton>(() => new Singleton());
private Singleton() { }
public static Singleton Instance => instance.Value;
}

This approach ensures thread safety and lazy initialization without locks.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

  • Global state: Singleton can lead to hidden dependencies and make testing difficult.
  • Tight coupling: Other classes depend on the Singleton instance, reducing flexibility.
  • Concurrency issues: If not implemented thread-safe, it can cause race conditions.
  • Resource contention: Singleton might become a bottleneck if overused in

concurrent environments.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Singletons can hinder unit testing because they introduce global state, making tests

dependent on a shared instance. This can cause tests to be flaky or order-dependent. To

mitigate this, use interfaces and dependency injection, or design the Singleton to allow

resetting its state for tests.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

container, though generally discouraged.

What interviewers expect

  • A clear definition tied to SOLID in Design Patterns & SOLID projects
  • Trade-offs (performance, maintainability, security, cost)
  • When you would and would not use it in production

Real-world example

In a production Design Patterns & SOLID application, teams apply this when handling user-facing features or integration boundaries. For example, you might use it during a sprint where reliability and observability matter—logging metrics, validating edge cases, and documenting the decision in an ADR so future developers understand why the approach was chosen.

How to explain in the interview

  1. Define the concept in one or two sentences.
  2. Context — where it fits in Design Patterns & SOLID architecture.
  3. Example — a specific project, bug, or performance win.
  4. Trade-off — what you gain vs what you sacrifice.

Tip: Practice aloud on Toolliyo mock interview or the Interview Q&A section before your real interview.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

  • Eager Initialization: The Singleton instance is created at the time of class loading.

It's simple but can waste resources if the instance is never used.

  • Lazy Initialization: The instance is created only when it is first accessed. It saves

resources but requires careful implementation for thread safety.

Factory pattern Q&A

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

The Factory pattern is a creational design pattern that provides an interface for creating

objects but allows subclasses or implementations to decide which class to instantiate. It’s

used to encapsulate object creation, promoting loose coupling and flexibility when the exact

types of objects aren’t known until runtime.

Use case: When a class can’t anticipate the class of objects it needs to create, or when you

want to delegate responsibility for object creation to subclasses.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

  • Factory Method: Defines an interface for creating an object but lets subclasses

decide which class to instantiate. It uses inheritance and relies on subclass

overriding.

  • Abstract Factory: Provides an interface to create families of related or dependent

objects without specifying their concrete classes. It uses composition and is useful

when you need to create multiple related objects together.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

A simple example of Factory Method:

// Product interface

public interface IAnimal
{

void Speak();

}

// Concrete Products

public class Dog : IAnimal
{
public void Speak() => Console.WriteLine("Woof");
}
public class Cat : IAnimal
{
public void Speak() => Console.WriteLine("Meow");
}

// Factory

public class AnimalFactory
{
public static IAnimal CreateAnimal(string animalType)
{
return animalType.ToLower() switch
{

"dog" => new Dog(),

"cat" => new Cat(),

_ => throw new ArgumentException("Invalid animal type")

};

}
}

Usage:

var dog = AnimalFactory.CreateAnimal("dog");

dog.Speak(); // Outputs: Woof

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

  • Encapsulates object creation: Decouples client code from concrete classes.
  • Promotes code reuse: Centralizes object creation logic.
  • Enhances maintainability: Adding new types requires minimal changes to existing

code.

  • Supports polymorphism: Clients work with interfaces or base classes rather than

concrete types.

  • Improves testability: Can easily mock or swap factory implementations.
Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Yes! Factory pattern can complement Dependency Injection (DI) by abstracting complex

object creation logic, especially when the creation involves runtime parameters or complex

setup that DI containers can’t handle easily.

Example: Imagine a service that needs different data repositories based on a runtime

parameter.

public interface IRepository { void Save(); }
public class SqlRepository : IRepository { public void Save() =>

Console.WriteLine("Saving to SQL DB"); }

public class InMemoryRepository : IRepository { public void Save()
=> Console.WriteLine("Saving in Memory"); }
public interface IRepositoryFactory
{

IRepository CreateRepository(string repoType);

}
public class RepositoryFactory : IRepositoryFactory
{
public IRepository CreateRepository(string repoType)
{
return repoType.ToLower() switch
{

"sql" => new SqlRepository(),

"memory" => new InMemoryRepository(),

_ => throw new ArgumentException("Invalid repository

type")

};

}
}

// Consumer class with DI

public class Service
{
private readonly IRepositoryFactory _repositoryFactory;
public Service(IRepositoryFactory repositoryFactory)
{
_repositoryFactory = repositoryFactory;
}
public void SaveData(string repoType)
{
var repo = _repositoryFactory.CreateRepository(repoType);

repo.Save();

}
}

Here, DI injects the IRepositoryFactory while the factory manages object creation

based on runtime input. This promotes loose coupling and flexibility.

Strategy Design Pattern

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

The Strategy pattern is a behavioral design pattern that defines a family of algorithms,

encapsulates each one, and makes them interchangeable at runtime.

It allows the algorithm to vary independently from clients that use it.

Problem it solves:

voids large if-else or switch statements when selecting behavior and promotes

flexibility by decoupling the algorithm from the client using it.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Example: Payment strategy selection

// Strategy Interface

public interface IPaymentStrategy
{

void Pay(decimal amount);

}

// Concrete Strategies

public class CreditCardPayment : IPaymentStrategy
{
public void Pay(decimal amount) => Console.WriteLine($"Paid

{amount} using Credit Card");

}
public class PayPalPayment : IPaymentStrategy
{
public void Pay(decimal amount) => Console.WriteLine($"Paid

{amount} using PayPal");

}

// Context

public class PaymentContext
{
private IPaymentStrategy _paymentStrategy;
public PaymentContext(IPaymentStrategy paymentStrategy)
{
_paymentStrategy = paymentStrategy;
}
public void ExecutePayment(decimal amount)
{

_paymentStrategy.Pay(amount);

}
}

Usage:

var context = new PaymentContext(new PayPalPayment());

context.ExecutePayment(200); // Outputs: Paid 200 using PayPal

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Answer: Payment gateways (Credit Card, PayPal, UPI, etc.) Sorting algorithms (QuickSort, MergeSort, BubbleSort) Authentication strategies (OAuth, JWT, LDAP) Compression algorithms (ZIP, RAR, TAR) Loggers (FileLogger, ConsoleLogger, DatabaseLogger)

What interviewers expect

  • A clear definition tied to SOLID in Design Patterns & SOLID projects
  • Trade-offs (performance, maintainability, security, cost)
  • When you would and would not use it in production

Real-world example

In a production Design Patterns & SOLID application, teams apply this when handling user-facing features or integration boundaries. For example, you might use it during a sprint where reliability and observability matter—logging metrics, validating edge cases, and documenting the decision in an ADR so future developers understand why the approach was chosen.

How to explain in the interview

  1. Define the concept in one or two sentences.
  2. Context — where it fits in Design Patterns & SOLID architecture.
  3. Example — a specific project, bug, or performance win.
  4. Trade-off — what you gain vs what you sacrifice.

Tip: Practice aloud on Toolliyo mock interview or the Interview Q&A section before your real interview.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

It promotes the Open/Closed Principle by allowing you to add new strategies (algorithms

or behaviors) without modifying the existing code.

The context class uses an interface for the strategy, so new behavior can be added just by

creating a new class that implements the interface—no need to touch existing logic.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Aspect Strategy Pattern State Pattern

Purpose Encapsulates interchangeable

behaviors (algorithms).

Encapsulates states and transitions

between them.

Client

Control

Client decides which strategy to use. Object changes its own state

internally.

Behavior

Switch

Switched externally (e.g., passed as

parameter).

Switched internally (e.g., via

method call).

Example Payment method selection. Document lifecycle (Draft →

Published → Archived).

Repository Design Pattern

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

The Repository pattern abstracts the data access layer from the business logic by providing

a collection-like interface to access domain objects.

It helps keep data access logic centralized and makes the codebase easier to maintain,

test, and swap out data sources (e.g., switching from EF Core to Dapper or an API).

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

pplications?

The Repository pattern abstracts the data access layer from the business logic by providing

collection-like interface to access domain objects.

It helps keep data access logic centralized and makes the codebase easier to maintain,

test, and swap out data sources (e.g., switching from EF Core to Dapper or an API).

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Here's a basic example:

// Entity

public class Product
{
public int Id { get; set; }
public string Name { get; set; }
}

// Generic Repository Interface

public interface IRepository<T> where T : class
{

Task<IEnumerable<T>> GetAllAsync();

Task<T> GetByIdAsync(int id);

Task AddAsync(T entity);

void Update(T entity);

void Delete(T entity);

Task SaveAsync();

}

// EF Core implementation

public class Repository<T> : IRepository<T> where T : class
{
private readonly DbContext _context;
private readonly DbSet<T> _dbSet;
public Repository(DbContext context)
{
_context = context;
_dbSet = context.Set<T>();
}
public async Task<IEnumerable<T>> GetAllAsync() => await

_dbSet.ToListAsync();

public async Task<T> GetByIdAsync(int id) => await

_dbSet.FindAsync(id);

public async Task AddAsync(T entity) => await

_dbSet.AddAsync(entity);

public void Update(T entity) => _dbSet.Update(entity);
public void Delete(T entity) => _dbSet.Remove(entity);
public async Task SaveAsync() => await

_context.SaveChangesAsync();

}
Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Answer: Separation of concerns between business and data access layers Improved testability (can mock repositories) Centralized query logic for maintainability Easier to switch persistence implementations Promotes cleaner and more organized code

What interviewers expect

  • A clear definition tied to SOLID in Design Patterns & SOLID projects
  • Trade-offs (performance, maintainability, security, cost)
  • When you would and would not use it in production

Real-world example

In a production Design Patterns & SOLID application, teams apply this when handling user-facing features or integration boundaries. For example, you might use it during a sprint where reliability and observability matter—logging metrics, validating edge cases, and documenting the decision in an ADR so future developers understand why the approach was chosen.

How to explain in the interview

  1. Define the concept in one or two sentences.
  2. Context — where it fits in Design Patterns & SOLID architecture.
  3. Example — a specific project, bug, or performance win.
  4. Trade-off — what you gain vs what you sacrifice.

Tip: Practice aloud on Toolliyo mock interview or the Interview Q&A section before your real interview.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

  • Add custom methods in a specialized repository interface (e.g.,

IProductRepository)

  • Use Specification pattern or LINQ expressions
  • Inject DbContext into repository if needed for advanced queries
  • Optionally, break out complex queries into Query objects or services
public interface IProductRepository : IRepository<Product>
{

Task<IEnumerable<Product>> GetProductsWithLowStockAsync(int

threshold);

}
Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

  • Over-abstraction: Can add unnecessary complexity for simple apps.
  • Duplication: May duplicate what EF Core already provides (since EF is already a

repository/unit-of-work pattern).

  • Hides EF Core features: May obscure advanced capabilities like eager loading or

projections.

  • Extra boilerplate: Especially with generic repositories, which may not add much

value.

Unit of Work

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

The Unit of Work pattern is a design pattern used to maintain a list of operations to be

performed within a single transaction. It ensures that all operations either succeed or fail

together, providing consistency and managing changes to multiple business objects during a

transaction. It coordinates the writing out of changes and resolves potential concurrency

issues.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

The Repository pattern abstracts the data access layer, providing a simplified interface to

data operations. The Unit of Work pattern complements it by managing multiple repositories

nd ensuring that all changes made through these repositories are committed in a single

transaction. This combination separates concerns, promotes clean architecture, and

maintains transactional integrity across multiple operations.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

In a .NET application (especially using Entity Framework), the Unit of Work is typically

implemented around the DbContext, as it already tracks changes and handles

transactions. Here's a simplified example:

// IUnitOfWork.cs

public interface IUnitOfWork : IDisposable
{

IProductRepository Products { get; }

ICustomerRepository Customers { get; }

int Complete();
}

// UnitOfWork.cs

public class UnitOfWork : IUnitOfWork
{
private readonly AppDbContext _context;
public IProductRepository Products { get; private set; }
public ICustomerRepository Customers { get; private set; }
public UnitOfWork(AppDbContext context)
{
_context = context;
Products = new ProductRepository(_context);
Customers = new CustomerRepository(_context);
}
public int Complete()
{
return _context.SaveChanges(); // All changes in one

transaction

}
public void Dispose()
{

_context.Dispose();

}
}

Then register it using Dependency Injection in Startup.cs or Program.cs:

services.AddScoped<IUnitOfWork, UnitOfWork>();

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

  • Transactional consistency: All changes across repositories are saved in a single

transaction.

  • Centralized commit: All changes are committed through one method

(Complete()), improving control and readability.

  • Reduced code duplication: Prevents repeated save logic across repositories.
  • Improved testability: Enables better unit testing by mocking a single Unit of Work

instead of multiple repositories.

  • Change tracking: Ensures that only modified entities are persisted, reducing

unnecessary database operations.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Yes, combining Unit of Work with Dependency Injection (DI) is a best practice in modern

.NET applications. DI allows the Unit of Work to be injected into services or controllers,

managing its lifecycle effectively. This improves modularity, promotes loose coupling, and

makes the application easier to maintain and test.

Example using constructor injection in a service:

public class OrderService
{
private readonly IUnitOfWork _unitOfWork;
public OrderService(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public void PlaceOrder(Order order)
{

_unitOfWork.Orders.Add(order);

_unitOfWork.Complete();

}
}

Dependency Injection (DI)

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Dependency Injection (DI) is a design pattern that allows an object to receive its

dependencies from an external source rather than creating them itself. This promotes loose

coupling, enhances testability, and simplifies code maintenance.

Benefits:

  • Improves modularity
  • Enables easier unit testing (via mock dependencies)
  • Promotes adherence to SOLID principles (especially the Dependency Inversion

Principle)

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

.NET Core has a built-in DI container that's tightly integrated into the framework. When

you create a new ASP.NET Core project, DI is configured automatically and used in

controllers, middleware, services, etc. You register dependencies in the Program.cs or

Startup.cs file using IServiceCollection.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Services are registered in the Program.cs or Startup.cs file using the

IServiceCollection interface. Example:

builder.Services.AddTransient<IProductService, ProductService>();

builder.Services.AddScoped<IOrderService, OrderService>();

builder.Services.AddSingleton<ILoggingService, LoggingService>();

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

  • Transient: A new instance is created every time it is requested.
  • Scoped: A single instance is created per request/HTTP request.
  • Singleton: A single instance is created and shared across the application lifetime.

Lifetime Created Per Use Case

Transient Every injection Lightweight, stateless services

Scoped HTTP Request Web services handling per-request

data

Singleton App lifetime Logging, configuration, cache

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Circular dependencies occur when two or more services depend on each other, creating an

infinite loop. To handle them:

  • Refactor the code to remove tight coupling.
  • Use interfaces or events to break the cycle.
  • Consider using property injection carefully (not recommended as a first choice).
  • Rethink your design – circular dependencies often indicate architectural issues.
Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

  • Easier mocking of dependencies using frameworks like Moq or NSubstitute.
  • No need to instantiate real implementations (e.g., database access) for tests.
  • Improved isolation of the unit under test.
  • Faster, more reliable tests due to lack of external dependency reliance.
Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Yes, DI can be implemented manually without using a DI container. You simply pass

dependencies through constructors or methods:

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

// Manual injection

var repo = new OrderRepository();
var service = new OrderService(repo);

This is suitable for small or simple applications, though not scalable for large apps.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

  • Over-injection (too many dependencies in one class – violates SRP)
  • Service locator anti-pattern
  • Incorrect lifetimes, leading to memory leaks or unintended reuse
  • Tight coupling to the DI container (e.g., using container APIs in business logic)
  • Circular dependencies due to poor design
  • Registering services in the wrong order or not at all
Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Inversion of Control (IoC) is a broader principle where control over object creation and

dependency resolution is transferred from the class itself to an external framework or

container.

Dependency Injection is a specific implementation of IoC, where the dependencies are

injected into a class rather than the class creating them internally. So, DI is one way to

chieve IoC.

Single Responsibility Principle

(SRP)

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

The Single Responsibility Principle (SRP) states that a class should have only one

reason to change. In other words, it should have only one responsibility or job.

Each class should do one thing, and do it well.

For example, a class that handles user authentication should not also be responsible for

logging or sending emails.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

You can identify SRP violations by asking questions like:

  • Does this class perform more than one function (e.g., data access and business

logic)?

  • Does it change for different reasons (e.g., changes in UI and database)?
  • Does it have too many dependencies or too much code?
  • Are there “and”s in the class name or method descriptions? E.g.,

ReportGeneratorAndPrinter.

Common signs:

  • Long classes or large files
  • Many unrelated methods
  • Hard-to-test code
Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Before (SRP Violation):

public class Invoice
{
public void GenerateInvoice() { /* logic */ }
public void SaveToDatabase() { /* logic */ }
public void SendEmail() { /* logic */ }
}

This class has 3 responsibilities: generating, saving, and emailing.

fter (SRP-compliant):

public class InvoiceGenerator
{
public void Generate() { /* logic */ }
}
public class InvoiceRepository
{
public void Save(Invoice invoice) { /* logic */ }
}
public class EmailService
{
public void Send(Invoice invoice) { /* logic */ }
}

Now each class has a single reason to change.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

SRP improves maintainability by:

  • Reducing complexity – Classes are smaller and easier to understand.
  • Easier testing – Each class can be tested in isolation.
  • Better separation of concerns – Business logic, data access, and infrastructure

code are kept apart.

  • Lower risk of bugs – Changes in one responsibility don’t affect others.

Ultimately, it leads to more modular, flexible, and robust code.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

If a class has multiple responsibilities:
  • It becomes tightly coupled and harder to change without affecting other parts.
  • Changes are more error-prone and often introduce bugs.
  • Testing becomes harder since the class relies on multiple behaviors.
  • Code reusability and readability suffer due to mixed concerns.
  • You violate SRP, which makes code harder to maintain in the long run.

Open/Closed Principle (OCP)

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

The Open/Closed Principle (OCP) states that:

Software entities (classes, modules, functions) should be open for

extension but closed for modification.

This means you should be able to add new behavior to a class without changing its

existing code, which helps avoid breaking existing functionality.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

To design classes that follow OCP:

  • Use abstraction (interfaces or abstract classes).
  • Rely on polymorphism and inheritance.
  • Apply composition over inheritance when suitable.
  • Follow design principles like Strategy, Decorator, or Template Method patterns.

✅ Extend behavior through new classes rather than modifying existing code.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Several design patterns are built around the idea of making systems extensible without

modifying core logic:

Pattern How It Helps With OCP

Strategy Allows changing behavior by swapping strategies.

Decorator Adds new responsibilities dynamically without changing original code.

Template Method Allows subclasses to override certain steps in an algorithm.

Factory Method Makes it easy to introduce new types without altering existing logic.

Observer Extends behavior in reaction to events without altering the source.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Before (OCP Violation):

public class DiscountCalculator
{
public decimal CalculateDiscount(string customerType)
{
if (customerType == "Regular") return 10;
if (customerType == "Premium") return 20;
if (customerType == "VIP") return 30;
return 0;
}
}
If you need to support a new customer type, you must modify this method — violating OCP.

fter (OCP Compliant):

public interface IDiscountStrategy
{

decimal GetDiscount();

}
public class RegularCustomerDiscount : IDiscountStrategy
{
public decimal GetDiscount() => 10;
}
public class PremiumCustomerDiscount : IDiscountStrategy
{
public decimal GetDiscount() => 20;
}
public class VipCustomerDiscount : IDiscountStrategy
{
public decimal GetDiscount() => 30;
}

Now you can add new customer types without modifying existing code — just create a new

strategy.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

  • Interfaces and abstract classes provide a contract that other classes can

implement or inherit.

  • They enable polymorphism, which allows behavior to be extended without altering

existing code.

  • By programming to abstractions (not concrete implementations), you can easily
introduce new behavior (via new implementations) while keeping the core logic

unchanged.

✅ OCP encourages extending via new subclasses or interface implementations, not

modifying existing ones.

Liskov Substitution Principle (LSP)

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

The Liskov Substitution Principle (LSP) states that:

Subtypes must be substitutable for their base types without altering the

correctness of the program.

In other words, if class S is a subclass of class T, then objects of type T should be

replaceable with objects of type S without breaking the application.

This ensures that inheritance models is-a relationships correctly.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Violating LSP can lead to:

  • Unexpected behavior when a subclass does not honor the contract of the base
class.
  • Code that breaks at runtime when substituting a derived class.
  • Tightly coupled code that depends on specific implementations rather than

bstractions.

  • Unit tests failing when testing subclasses in place of base classes.

Essentially, it defeats the purpose of polymorphism.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Example (Violation of LSP):

public class Rectangle
{
public virtual int Width { get; set; }
public virtual int Height { get; set; }
public int Area() => Width * Height;
}
public class Square : Rectangle
{
public override int Width
{
set { base.Width = base.Height = value; }
}
public override int Height
{
set { base.Width = base.Height = value; }
}
}

Now if you substitute Rectangle with Square:

Rectangle rect = new Square();
rect.Width = 5;
rect.Height = 10;

Console.WriteLine(rect.Area()); // Outputs 100, but logically

expected 50

❌ The behavior is incorrect — this is a violation of LSP.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

To ensure subclasses follow LSP:

  • Subclasses should not override behavior in a way that breaks expected behavior.
  • Subclasses should preserve the invariants and preconditions/postconditions of the

base class.

  • Avoid overriding methods to throw exceptions for valid base class behavior.
  • Use composition over inheritance if a subclass doesn’t strictly conform to the base
class behavior.
  • Write unit tests to verify that the subclass behaves identically to the base class in all

valid scenarios.

✅ Ask yourself: Can this subclass be used anywhere the base class is used — without

surprises?

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

LSP is fundamentally about correct use of inheritance. While inheritance allows code

reuse, LSP ensures that the behavior of subclasses remains consistent with that of the

base class.

If a subclass changes the meaning or violates the expectations of the base class’s

behavior, it's misusing inheritance.

Interface Segregation Principle (ISP)
Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Answer: No client should be forced to implement methods it does not use. Break large interfaces into smaller, focused interfaces.

What interviewers expect

  • A clear definition tied to SOLID in Design Patterns & SOLID projects
  • Trade-offs (performance, maintainability, security, cost)
  • When you would and would not use it in production

Real-world example

In a production Design Patterns & SOLID application, teams apply this when handling user-facing features or integration boundaries. For example, you might use it during a sprint where reliability and observability matter—logging metrics, validating edge cases, and documenting the decision in an ADR so future developers understand why the approach was chosen.

How to explain in the interview

  1. Define the concept in one or two sentences.
  2. Context — where it fits in Design Patterns & SOLID architecture.
  3. Example — a specific project, bug, or performance win.
  4. Trade-off — what you gain vs what you sacrifice.

Tip: Practice aloud on Toolliyo mock interview or the Interview Q&A section before your real interview.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Small, specific interfaces:

  • Promote separation of concerns
  • Make classes easier to implement and test
  • Reduce the risk of breaking changes
  • Avoid forcing classes to implement irrelevant methods
  • Increase reusability and readability

In contrast, large interfaces force classes to implement methods they may not need —

leading to fragile and cluttered code.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

ISP improves code flexibility by:

  • Allowing classes to only depend on what they actually use
  • Making it easier to extend or replace functionality without affecting unrelated parts
  • Enabling composition over inheritance
  • Making interfaces easier to mock or stub in unit tests
  • Encouraging clean, modular design

Smaller interfaces result in lower coupling and better maintainability.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Violation Example:

public interface IWorker
{

void Work();

void Eat();

void Sleep();

}
public class Robot : IWorker
{
public void Work() { /* logic */ }
public void Eat() { throw new NotImplementedException(); }
public void Sleep() { throw new NotImplementedException(); }
}

❌ Robot is forced to implement Eat() and Sleep(), which don’t make sense for it.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Refactored Using ISP:

public interface IWorkable
{

void Work();

}
public interface IFeedable
{

void Eat();

}
public interface ISleepable
{

void Sleep();

}
public class Human : IWorkable, IFeedable, ISleepable
{
public void Work() { }
public void Eat() { }
public void Sleep() { }
}
public class Robot : IWorkable
{
public void Work() { }
}

✅ Now each class implements only the interfaces it needs — in line with ISP.

Inversion Principle (DIP)

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

The Dependency Inversion Principle (DIP) states that:

High-level modules should not depend on low-level modules. Both should

depend on abstractions.

bstractions should not depend on details. Details should depend on

bstractions.

In other words:

  • High-level business logic shouldn't depend on concrete implementations.
  • Instead, both high- and low-level components should depend on interfaces or

bstract classes.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Aspect Dependency Inversion Principle (DIP) Dependency Injection (DI)

Definitio

design principle about depending on

bstractions

technique for passing

dependencies

Goal Decouple high-level logic from low-level

details

Provide dependencies to

objects

Relation DIP motivates the need for DI DI is a way to implement DIP

Focus What to depend on (abstractions) How dependencies are supplied

✅ DIP is a design principle, while DI is a design pattern/technique to implement that

principle.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Abstractions (e.g., interfaces or abstract classes):

  • Decouple components so changes in one don’t ripple through others
  • Enable substitution of different implementations easily
  • Allow for easier unit testing with mocks/stubs
  • Promote extensibility and maintainability
  • Serve as contracts that both high- and low-level modules depend on
Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

❌ Without DIP (Tightly Coupled):

public class FileLogger
{
public void Log(string message) => Console.WriteLine("File log:

" + message);

}
public class OrderService
{
private readonly FileLogger _logger = new FileLogger();
public void ProcessOrder()
{

// Logic

_logger.Log("Order processed.");

}
}
  • OrderService is tightly coupled to FileLogger.

✅ With DIP (Loosely Coupled via Abstraction):

public interface ILogger
{

void Log(string message);

}
public class FileLogger : ILogger
{
public void Log(string message) => Console.WriteLine("File log:

" + message);

}
public class OrderService
{
private readonly ILogger _logger;
public OrderService(ILogger logger)
{
_logger = logger;
}
public void ProcessOrder()
{

// Logic

_logger.Log("Order processed.");

}
}

Now OrderService depends on the abstraction (ILogger), not the concrete

FileLogger. You can easily substitute with DatabaseLogger, ConsoleLogger, or a

mock in tests.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

✅ Key Benefits:

  • Decouples components — changes in low-level modules won’t affect high-level

ones

  • Improves testability — you can easily inject mocks/stubs
  • Enhances flexibility — swap implementations without touching core logic
  • Promotes reuse — abstractions can be used across different modules
  • Supports SOLID architecture — especially when combined with DI and IoC

containers

dvanced & Scenario-Based

Questions

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Design patterns provide structured, reusable solutions that embody SOLID principles. For

example, the Strategy pattern supports OCP by allowing behavior extension without

modifying existing code; Repository separates data access (SRP); Dependency Injection

supports DIP by decoupling high- and low-level modules. Using patterns helps keep code

clean, modular, and maintainable.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

The Unit of Work coordinates multiple Repositories and commits changes in a single

transaction. For example:

public interface IUnitOfWork : IDisposable
{

IProductRepository Products { get; }

IOrderRepository Orders { get; }

int Complete();
}
public class UnitOfWork : IUnitOfWork
{
private readonly DbContext _context;
public IProductRepository Products { get; }
public IOrderRepository Orders { get; }
public UnitOfWork(DbContext context)
{
_context = context;
Products = new ProductRepository(_context);
Orders = new OrderRepository(_context);
}
public int Complete() => _context.SaveChanges();
public void Dispose() => _context.Dispose();
}

This ensures atomic commits across repositories.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Testing singletons/statics is tricky due to global state. Best practices include:

  • Refactor to use interfaces and DI instead of static/singletons.
  • Wrap static calls behind interfaces so you can mock them.
  • Use specialized mocking tools (e.g., Microsoft Fakes) if refactoring isn't possible.
  • Avoid static state to improve testability.
Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

The Mediator Pattern centralizes communication between components, preventing direct

dependencies and reducing complexity. It promotes loose coupling and simplifies

interactions. Alternatively, the Observer Pattern enables event-driven decoupling, and

Facade Pattern provides a simplified interface to complex subsystems.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

nd why?

The Mediator Pattern centralizes communication between components, preventing direct

dependencies and reducing complexity. It promotes loose coupling and simplifies

interactions. Alternatively, the Observer Pattern enables event-driven decoupling, and

Facade Pattern provides a simplified interface to complex subsystems.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Define a common interface, e.g., IPaymentStrategy with a method Pay(). Implement

concrete strategies for each payment method (CreditCard, PayPal, etc.). Use a context class

to invoke the selected strategy at runtime, enabling easy extension without modifying

existing code.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

DAO (Data Access Object) focuses on low-level database operations and CRUD, typically

mapping tables to objects.

Repository abstracts data access at the domain level, working with aggregates/entities and

encapsulating business logic. Repository often uses DAO internally but is more aligned with

domain-driven design.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

  • Identify classes violating SRP and break them down.
  • Introduce abstractions and interfaces to decouple components (DIP).
  • Replace conditional logic with polymorphism to respect OCP.
  • Split large interfaces (ISP).
  • Check inheritance hierarchies to maintain LSP.
  • Inject dependencies instead of direct instantiation.
  • Incrementally refactor with unit tests to ensure behavior remains consistent.
Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Use AOP (Aspect-Oriented Programming) techniques or design patterns like Decorator

to separate cross-cutting concerns from business logic. In .NET, middleware, filters, or

interceptors can manage concerns like logging or authorization, keeping SRP intact.
Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

DI containers use reflection to inspect constructors of requested services, resolve

dependencies recursively from their registrations, apply lifecycle scopes (Singleton, Scoped,

Transient), and build the full object graph to return fully constructed instances.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

  • Define plugin contracts with interfaces (DIP).
  • Load plugins dynamically using reflection or MEF.
  • Use DI to inject dependencies into plugins.
  • Ensure plugins follow SRP with focused responsibilities.
  • Use Factory or Strategy patterns to instantiate plugins.
  • Keep core system closed for modification but open for extension (OCP).
  • Separate cross-cutting concerns externally.

Practical .NET Questions

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

ASP.NET Core MVC has built-in support for Dependency Injection.

  • Register services in Startup.cs within ConfigureServices method using

IServiceCollection:

public void ConfigureServices(IServiceCollection services)
{

services.AddControllersWithViews();

services.AddScoped<IProductService, ProductService>(); //

Example

}
  • Inject dependencies via constructor injection in controllers or services:
public class HomeController : Controller
{
private readonly IProductService _productService;
public HomeController(IProductService productService)
{
_productService = productService;
}
public IActionResult Index()
{
var products = _productService.GetAll();
return View(products);
}
}

The framework resolves and injects dependencies automatically.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

  • IServiceCollection: A container used during app startup to register services and

their lifetimes (Scoped, Transient, Singleton). It acts as a service registry.

  • IServiceProvider: The built container that resolves and provides instances of

registered services at runtime. It uses the registrations to create and inject

dependencies.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

  • Register DbContext with DI in Startup.cs:

services.AddDbContext<AppDbContext>(options =>

options.UseSqlServer(Configuration.GetConnectionString("DefaultConne

ction")));

  • Implement Repositories for entities injecting AppDbContext.
  • Implement Unit of Work which holds multiple repositories and calls SaveChanges()

on the DbContext:

public interface IUnitOfWork : IDisposable
{

IProductRepository Products { get; }

int Complete();
}
public class UnitOfWork : IUnitOfWork
{
private readonly AppDbContext _context;
public IProductRepository Products { get; private set; }
public UnitOfWork(AppDbContext context)
{
_context = context;
Products = new ProductRepository(_context);
}
public int Complete() => _context.SaveChanges();
public void Dispose() => _context.Dispose();
}

Register UnitOfWork in DI container as Scoped.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

  • Use mocking libraries like Moq, NSubstitute, or FakeItEasy.
  • Create mocks of interfaces and inject them into the class under test:
var mockRepo = new Mock<IProductRepository>();

mockRepo.Setup(repo => repo.GetAll()).Returns(new List<Product> {

... });

var service = new ProductService(mockRepo.Object);

// Act & Assert

  • This allows testing in isolation without hitting real databases or external services.
Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

  • Chain of Responsibility: Middleware components form a pipeline where each

decides to pass control or handle the request.

  • Decorator: Middleware wraps around the next component, adding behavior before

or after.

  • Factory: Middleware components can be created via factories for configurable

pipeline setup.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

  • Define a caching interface:
public interface ICacheStrategy
{

void Cache(string key, object value);

object Retrieve(string key);

}
  • Implement strategies like MemoryCacheStrategy,

DistributedCacheStrategy.

  • Use DI or factory to inject the chosen strategy at runtime:
public class CacheContext
{
private readonly ICacheStrategy _cacheStrategy;
public CacheContext(ICacheStrategy cacheStrategy)
{
_cacheStrategy = cacheStrategy;
}
public void Cache(string key, object value) =>

_cacheStrategy.Cache(key, value);

}

This enables switching caching mechanisms without code changes.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

  • Abstract Factory: Provides an interface for creating families of related objects

without specifying concrete classes.

Example: Creating UI components for different OS (Windows, Mac).

  • Builder: Focuses on step-by-step construction of a complex object, allowing different

representations.

Example: Building a complex House with various parts (walls, doors, roof).

Summary: Abstract Factory is about families of products, Builder is about complex

construction process.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

  • Apply Single Responsibility Principle (SRP) by splitting responsibilities into smaller
classes.
  • Use composition instead of inheritance to delegate behavior.
  • Extract business logic into services or helpers.
  • Introduce abstractions to isolate concerns.
  • Continuously refactor large classes and add unit tests.
Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

  • Resharper: Provides code analysis and refactoring hints.
  • SonarQube / SonarCloud: Analyzes code quality and reports SOLID violations.
  • FxCop / Roslyn analyzers: Provide static analysis with custom rules.
  • NDepend: Deep architecture and dependency analysis tool.
  • StyleCop: Enforces coding style which indirectly helps maintain SOLID code.
Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

  • Mediator decouples components by centralizing communication, supporting SRP and

DIP by reducing direct dependencies.

  • It fits DI because the mediator itself can be injected where needed.
  • It supports OCP by allowing new communication routes or handlers without

modifying existing components.

  • Helps avoid tight coupling in complex workflows or CQRS patterns.

Behavioral / Conceptual Questions

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

In a recent project, we had a monolithic service class handling multiple responsibilities,

making it hard to maintain and extend. By applying Single Responsibility Principle (SRP),

we split the class into focused services, each with a clear purpose. This drastically improved

readability, reduced bugs, and made it easier to add new features without risking

regressions. The project became more testable because each small class could be unit

tested independently.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

pplications?

Yes. In one project, a singleton was used without thread safety, causing race conditions

when accessed concurrently. This led to inconsistent state and application crashes. We

resolved it by implementing thread-safe lazy initialization using Lazy<T> in .NET, ensuring

the singleton instance was created safely once, even under heavy parallel access.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Yes. In one project, a singleton was used without thread safety, causing race conditions

when accessed concurrently. This led to inconsistent state and application crashes. We

resolved it by implementing thread-safe lazy initialization using Lazy<T> in .NET, ensuring

the singleton instance was created safely once, even under heavy parallel access.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

I prioritize YAGNI (You Aren’t Gonna Need It) to avoid over-engineering. SOLID principles

guide design for flexibility and maintainability, but I apply them pragmatically: start with

simple solutions and refactor as requirements evolve. Writing tests early helps identify pain

points justifying additional abstractions. Communication with the team ensures we don’t add

complexity prematurely but keep the codebase adaptable.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Challenges include:

  • Legacy code with tight coupling, making decomposition hard.
  • Risk of introducing bugs while splitting responsibilities or introducing abstractions.
  • Managing dependencies and lifetimes correctly when injecting dependencies.
  • Convincing stakeholders that refactoring time is valuable.
  • Balancing between adhering strictly to SOLID vs. keeping code understandable and

performant.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

I use a combination of:

  • Simple examples showing before/after code refactoring.
  • Pair programming sessions to explain thought processes.
  • Encouraging reading and discussing classic books like “Clean Code” and “Design

Patterns”.

  • Practical coding exercises and code reviews focused on SOLID principles.
  • Showing real project scenarios where principles improved code quality and

maintainability.

  • Promoting a culture of continuous learning and curiosity.

Bonus / Miscellaneous

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

  • Inheritance creates an “is-a” relationship, where a subclass inherits behavior and

properties from a parent class. It can lead to tight coupling and fragile hierarchies if

overused.

  • Composition creates a “has-a” relationship, where a class contains instances of

other classes and delegates behavior to them. It’s more flexible and promotes loose

coupling.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

  • Decorator adds additional responsibilities to objects dynamically without altering

their interface. It wraps the original object to extend behavior.

  • Proxy controls access to an object, possibly adding lazy initialization, access control,

or logging, without changing its interface.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Answer: Adapter converts the interface of a class into another interface clients expect, allowing incompatible interfaces to work together. It promotes Open/Closed Principle (OCP) by enabling new integrations without modifying existing code.

What interviewers expect

  • A clear definition tied to SOLID in Design Patterns & SOLID projects
  • Trade-offs (performance, maintainability, security, cost)
  • When you would and would not use it in production

Real-world example

In a production Design Patterns & SOLID application, teams apply this when handling user-facing features or integration boundaries. For example, you might use it during a sprint where reliability and observability matter—logging metrics, validating edge cases, and documenting the decision in an ADR so future developers understand why the approach was chosen.

How to explain in the interview

  1. Define the concept in one or two sentences.
  2. Context — where it fits in Design Patterns & SOLID architecture.
  3. Example — a specific project, bug, or performance win.
  4. Trade-off — what you gain vs what you sacrifice.

Tip: Practice aloud on Toolliyo mock interview or the Interview Q&A section before your real interview.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Answer: Use the Proxy or Virtual Proxy pattern where a placeholder object controls access to the real object and defers its creation until needed. In .NET, Lazy&lt;T&gt; provides built-in lazy loading.

What interviewers expect

  • A clear definition tied to SOLID in Design Patterns & SOLID projects
  • Trade-offs (performance, maintainability, security, cost)
  • When you would and would not use it in production

Real-world example

In a production Design Patterns & SOLID application, teams apply this when handling user-facing features or integration boundaries. For example, you might use it during a sprint where reliability and observability matter—logging metrics, validating edge cases, and documenting the decision in an ADR so future developers understand why the approach was chosen.

How to explain in the interview

  1. Define the concept in one or two sentences.
  2. Context — where it fits in Design Patterns & SOLID architecture.
  3. Example — a specific project, bug, or performance win.
  4. Trade-off — what you gain vs what you sacrifice.

Tip: Practice aloud on Toolliyo mock interview or the Interview Q&A section before your real interview.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

  • Service Locator anti-pattern: Hides dependencies instead of injecting them

explicitly.

  • Overusing Singleton: Leads to hidden global state and testing difficulties.
  • Improper Singleton thread safety: Causes race conditions.
  • Injecting concrete implementations: Violates DIP.
Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Template Method defines the skeleton of an algorithm in a base class, deferring some steps

to subclasses. It allows subclasses to redefine parts of the algorithm without changing its

structure. It supports OCP by enabling extensions through inheritance.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

SOLID promotes small, single-responsibility services (SRP), clear interfaces (ISP), loose

coupling (DIP), and extendable design (OCP). This aligns well with microservices by

encouraging modular, maintainable, and testable service boundaries.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Answer: The Command Pattern encapsulates requests as objects, allowing operations to be stored, undone, or redone by maintaining command history.

What interviewers expect

  • A clear definition tied to SOLID in Design Patterns & SOLID projects
  • Trade-offs (performance, maintainability, security, cost)
  • When you would and would not use it in production

Real-world example

In a production Design Patterns & SOLID application, teams apply this when handling user-facing features or integration boundaries. For example, you might use it during a sprint where reliability and observability matter—logging metrics, validating edge cases, and documenting the decision in an ADR so future developers understand why the approach was chosen.

How to explain in the interview

  1. Define the concept in one or two sentences.
  2. Context — where it fits in Design Patterns & SOLID architecture.
  3. Example — a specific project, bug, or performance win.
  4. Trade-off — what you gain vs what you sacrifice.

Tip: Practice aloud on Toolliyo mock interview or the Interview Q&A section before your real interview.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Answer: Use interfaces and abstractions (DIP). Apply Dependency Injection. Modularize code into bounded contexts or separate projects. Use events or messaging for decoupled communication. Avoid static state and global variables.

What interviewers expect

  • A clear definition tied to SOLID in Design Patterns & SOLID projects
  • Trade-offs (performance, maintainability, security, cost)
  • When you would and would not use it in production

Real-world example

In a production Design Patterns & SOLID application, teams apply this when handling user-facing features or integration boundaries. For example, you might use it during a sprint where reliability and observability matter—logging metrics, validating edge cases, and documenting the decision in an ADR so future developers understand why the approach was chosen.

How to explain in the interview

  1. Define the concept in one or two sentences.
  2. Context — where it fits in Design Patterns & SOLID architecture.
  3. Example — a specific project, bug, or performance win.
  4. Trade-off — what you gain vs what you sacrifice.

Tip: Practice aloud on Toolliyo mock interview or the Interview Q&A section before your real interview.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Answer: Encapsulates a request as an object with methods to execute and possibly undo the operation. The invoker calls commands without knowing the action details, supporting decoupling and flexible request handling.

What interviewers expect

  • A clear definition tied to SOLID in Design Patterns & SOLID projects
  • Trade-offs (performance, maintainability, security, cost)
  • When you would and would not use it in production

Real-world example

In a production Design Patterns & SOLID application, teams apply this when handling user-facing features or integration boundaries. For example, you might use it during a sprint where reliability and observability matter—logging metrics, validating edge cases, and documenting the decision in an ADR so future developers understand why the approach was chosen.

How to explain in the interview

  1. Define the concept in one or two sentences.
  2. Context — where it fits in Design Patterns & SOLID architecture.
  3. Example — a specific project, bug, or performance win.
  4. Trade-off — what you gain vs what you sacrifice.

Tip: Practice aloud on Toolliyo mock interview or the Interview Q&A section before your real interview.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

  • Cohesion: Degree to which elements of a module belong together. High cohesion

means focused, well-defined responsibilities.

  • Coupling: Degree of interdependence between modules. Low coupling means

modules are independent and changes in one don’t affect others.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Answer: Use API contracts and versioning. Employ service discovery and load balancing. Prefer asynchronous messaging/event-driven architecture to reduce tight coupling. Apply circuit breakers and retries for fault tolerance.

What interviewers expect

  • A clear definition tied to SOLID in Design Patterns & SOLID projects
  • Trade-offs (performance, maintainability, security, cost)
  • When you would and would not use it in production

Real-world example

In a production Design Patterns & SOLID application, teams apply this when handling user-facing features or integration boundaries. For example, you might use it during a sprint where reliability and observability matter—logging metrics, validating edge cases, and documenting the decision in an ADR so future developers understand why the approach was chosen.

How to explain in the interview

  1. Define the concept in one or two sentences.
  2. Context — where it fits in Design Patterns & SOLID architecture.
  3. Example — a specific project, bug, or performance win.
  4. Trade-off — what you gain vs what you sacrifice.

Tip: Practice aloud on Toolliyo mock interview or the Interview Q&A section before your real interview.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Answer: Interfaces define contracts with no implementation, supporting ISP and DIP by llowing flexible implementations. Abstract classes provide a base implementation and shared code, useful for Template Method pattern and partial abstraction.

What interviewers expect

  • A clear definition tied to SOLID in Design Patterns & SOLID projects
  • Trade-offs (performance, maintainability, security, cost)
  • When you would and would not use it in production

Real-world example

In a production Design Patterns & SOLID application, teams apply this when handling user-facing features or integration boundaries. For example, you might use it during a sprint where reliability and observability matter—logging metrics, validating edge cases, and documenting the decision in an ADR so future developers understand why the approach was chosen.

How to explain in the interview

  1. Define the concept in one or two sentences.
  2. Context — where it fits in Design Patterns & SOLID architecture.
  3. Example — a specific project, bug, or performance win.
  4. Trade-off — what you gain vs what you sacrifice.

Tip: Practice aloud on Toolliyo mock interview or the Interview Q&A section before your real interview.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Builder separates complex object construction from its representation. For example, building

n HttpRequest with optional headers, query params, and body:

public class HttpRequestBuilder
{
private HttpRequestMessage _request = new HttpRequestMessage();
public HttpRequestBuilder SetMethod(HttpMethod method)
{
_request.Method = method;
return this;
}
public HttpRequestBuilder AddHeader(string key, string value)
{

_request.Headers.Add(key, value);

return this;
}
public HttpRequestMessage Build() => _request;
}

llows building requests step-by-step fluently.

Permalink

Design Patterns & SOLID Design Patterns in C# · SOLID

Answer: Observer supports SRP by separating notification logic from core business logic and DIP by depending on abstractions (observers). It fits DI because observers can be injected, allowing flexible runtime subscriptions and loose coupling.

What interviewers expect

  • A clear definition tied to SOLID in Design Patterns & SOLID projects
  • Trade-offs (performance, maintainability, security, cost)
  • When you would and would not use it in production

Real-world example

In a production Design Patterns & SOLID application, teams apply this when handling user-facing features or integration boundaries. For example, you might use it during a sprint where reliability and observability matter—logging metrics, validating edge cases, and documenting the decision in an ADR so future developers understand why the approach was chosen.

How to explain in the interview

  1. Define the concept in one or two sentences.
  2. Context — where it fits in Design Patterns & SOLID architecture.
  3. Example — a specific project, bug, or performance win.
  4. Trade-off — what you gain vs what you sacrifice.

Tip: Practice aloud on Toolliyo mock interview or the Interview Q&A section before your real interview.

Permalink
Toolliyo Assistant
Ask about tutorials, ebooks, training, pricing, mentor services, and support. I use public site content only—not admin or internal tools.

care@toolliyo.com

Need callback? Share your details