Interview Q&A

Master technical and career interviews with structured answers—short definition, real examples, pitfalls, and how to answer in 60–90 seconds.

4616 total questions 4516 technical 100 career & HR 4346 from PDF library

Showing 26–50 of 456

Career & HR topics

By tech stack

Mid PDF
Can DI be used without a DI container? How?

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(IOr…

SOLID Read answer
Mid PDF
What are common pitfalls when implementing DI?

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 A…

SOLID Read answer
Mid PDF
How does DI relate to Inversion of Control (IoC)?

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 specifi…

SOLID Read answer
Mid PDF
How can you identify violations of SRP in code?

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)? Do…

SOLID Read answer
Mid PDF
Can you give an example of refactoring code to follow SRP?

Before (SRP Violation): public class Invoice { public void GenerateInvoice() { /* logic */ } public void SaveToDatabase() { /* logic */ } public void SendEmail() { /* logic */ } } This class has 3 responsibilities: gener…

SOLID Read answer
Mid PDF
How does SRP improve maintainability?

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, an…

SOLID Read answer
Mid PDF
What happens if a class has multiple responsibilities?

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 relie…

SOLID Read answer
Mid PDF
What does the Open/Closed Principle mean?

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…

SOLID Read answer
Mid PDF
How can you design classes that are open for extension but closed for modification?

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, Decorat…

SOLID Read answer
Mid PDF
How does OCP relate to interfaces and abstract classes?

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 abstraction…

SOLID Read answer
Mid PDF
How can violating LSP cause issues in software design?

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 i…

SOLID Read answer
Mid PDF
How do you ensure subclasses follow LSP?

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 overrid…

SOLID Read answer
Mid PDF
How does LSP relate to inheritance?

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…

SOLID Read answer
Mid PDF
Why should interfaces be specific and small?

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 read…

SOLID Read answer
Mid PDF
How does ISP improve code flexibility?

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 Maki…

SOLID Read answer
Mid PDF
Can you provide an example of ISP violation?

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 v…

SOLID Read answer
Mid PDF
How do you refactor a fat interface to follow ISP?

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 vo…

SOLID Read answer
Mid PDF
How does DIP differ from Dependency Injection?

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 Pro…

SOLID Read answer
Mid PDF
How do abstractions help in DIP?

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/stub…

SOLID Read answer
Mid PDF
Can you explain DIP with an example in C#?

❌ 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 FileLogg…

SOLID Read answer
Mid PDF
What are the benefits of following DIP?

✅ 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…

SOLID Read answer
Mid PDF
Can you give an example where you combined Repository and Unit of Work patterns?

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…

SOLID Read answer
Mid PDF
How do you test classes that use Singleton or static instances?

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…

SOLID Read answer
Mid PDF
How do you apply Strategy pattern to implement multiple payment methods?

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, ena…

SOLID Read answer
Mid PDF
Can you explain how DI containers resolve dependencies at runtime?

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 grap…

SOLID Read answer

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 & share

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 & share

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 & share

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 & share

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 & share

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 & share

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 & share

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 & share

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 & share

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 & share

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 & share

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 & share

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 & share

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 & share

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 & share

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 & share

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 & share

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 & share

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 & share

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 & share

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 & share

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 & share

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 & share

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 & share

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 & share
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