C# Design Patterns Interview Questions for Senior .NET Developers (2026)

Senior .NET developers preparing for interviews are expected to demonstrate not just knowledge of GoF design patterns in theory, but the ability to apply C# design patterns in real ASP.NET Core applications โ at scale, in production. This guide covers the C# design patterns interview questions that actually come up at the senior level, with answers that go beyond textbook definitions and into the architectural decisions your interviewers care about.
๐ Want implementation-ready .NET source code you can drop straight into your project? Join Coding Droplets on Patreon for exclusive tutorials, premium code samples, and early access to new content. ๐ https://www.patreon.com/CodingDroplets
What Interviewers Are Actually Testing
At the senior level, interviewers rarely ask "what is the Singleton pattern?" They ask: "How do you register a Singleton correctly in ASP.NET Core DI, and what are the thread-safety implications?" The shift is from definition recall to architectural reasoning.
Design pattern questions at this level are usually attached to real scenarios โ a high-traffic API that needs to decouple processing, a multi-tenant system that requires different behaviours per tenant, or a financial service that needs to ensure exactly-once execution. Understanding patterns in isolation is not enough; you need to know when to use them, when they become liabilities, and how they compose in an ASP.NET Core dependency injection container.
Basic Design Pattern Questions
What Is the Difference Between a Creational, Structural, and Behavioural Pattern?
The Gang of Four (GoF) classification divides patterns into three families:
Creational patterns control how objects are created. Factory Method, Abstract Factory, Builder, Prototype, and Singleton all fall here. In .NET, the DI container is itself a creational infrastructure โ understanding how patterns like Factory and Builder compose with IServiceCollection is essential.
Structural patterns describe how objects and classes are composed into larger structures. Adapter, Decorator, Proxy, Composite, Bridge, Flyweight, and Facade belong here. In ASP.NET Core, the middleware pipeline is a Decorator chain, and HttpClient factory wrapping is a Proxy.
Behavioural patterns focus on communication and responsibility between objects. Strategy, Observer, Command, Chain of Responsibility, Iterator, Template Method, State, Visitor, Mediator, and Memento are the key ones. MediatR implements the Mediator pattern, and the pipeline behaviours in MediatR are a Chain of Responsibility.
How Does the Singleton Pattern Work in ASP.NET Core DI?
Registering a service as AddSingleton<T>() means the DI container creates one instance per container lifetime โ effectively the application lifetime for a typical ASP.NET Core app. The container manages the lifecycle, so you do not need to implement the private constructor anti-pattern that classic GoF Singleton requires.
Important caveats interviewers probe:
A Singleton service that captures a Scoped dependency at construction time will capture a stale scope โ this is the classic "captive dependency" bug
Singletons must be thread-safe because they are shared across all requests
IHostedServiceandBackgroundServiceimplementations run as Singletons by defaultStatic constructors in C# give you a thread-safe, lazy Singleton without any DI involvement โ but this bypasses testability
What Is the Repository Pattern and Why Do Some Teams Reject It With EF Core?
The Repository pattern abstracts data access behind an interface (IProductRepository) so that the domain layer does not depend on a specific persistence mechanism. It enables unit testing by mocking the repository interface.
The case against it with EF Core: DbContext already implements Unit of Work, and DbSet<T> already implements a queryable repository-like abstraction. Wrapping EF Core in a generic repository (IRepository<T>) often strips away EF-specific capabilities like AsNoTracking(), compiled queries, and IQueryable composition โ forcing you to add method after method to cover every data access shape.
The balanced answer: Use the Repository pattern for raw SQL, Dapper, or non-EF data sources. For EF Core, consider exposing the DbContext directly through an IUnitOfWork interface, or scope your repositories to aggregate roots following Domain-Driven Design.
Intermediate Design Pattern Questions
How Does the Strategy Pattern Differ From the State Pattern?
Both patterns involve switching behaviour at runtime, which is why they are frequently confused in interviews.
Strategy externalises an algorithm into a family of interchangeable classes. The context delegates work to a strategy object that is typically injected or chosen by the caller. The context itself does not change โ the strategy does. In ASP.NET Core, authentication handlers are classic Strategy implementations: AddJwtBearer, AddCookie, and AddApiKey are interchangeable authentication strategies injected into the pipeline.
State internalises transitions. The object knows its own state and transitions between states as a result of inputs. A background job that moves from Pending โ Running โ Completed โ Failed is a State machine. The context changes its own behaviour based on its internal state, rather than the caller choosing a strategy.
Interview signal: If you say "State is just Strategy with transitions" you demonstrate depth. If you explain how IAuthorizationHandler in ASP.NET Core uses a State-like design inside an authorization pipeline, you signal architectural fluency.
What Is the Decorator Pattern and Where Does ASP.NET Core Use It?
The Decorator pattern adds behaviour to an object by wrapping it in another object that implements the same interface. The wrapper forwards calls to the original, adding logic before or after.
ASP.NET Core's middleware pipeline is the most visible Decorator chain in the framework. Each call to Use() wraps the next middleware in a delegate that can execute logic before and after calling next(). Kestrel โ Routing โ Authentication โ Authorization โ your endpoint is one long Decorator chain executing in order.
In application code, the Decorator is commonly applied to add cross-cutting concerns to services without modifying them:
Wrapping
IProductRepositorywith a caching decoratorWrapping
IEmailServicewith a retry decoratorAdding logging or metrics around a command handler
The Decorator maintains Liskov Substitution โ callers do not know whether they are talking to the original or a decorated version, because both implement the same interface.
How Does the Proxy Pattern Differ From the Decorator?
Structural similarity between Proxy and Decorator often trips up candidates.
Proxy controls access to an object. The proxy mediates: it may delay creation (virtual proxy / lazy loading), enforce access control (protection proxy), or stand in for a remote object (remote proxy). The proxy often knows the concrete type it wraps; the caller typically does not choose what proxy it gets.
Decorator adds behaviour. It is typically stacked and composable โ you can apply multiple decorators in sequence. The decorator is often chosen by the composition root.
In .NET: Lazy<T> is a virtual proxy. IHttpClientFactory with DelegatingHandler is a Proxy chain for cross-cutting HTTP concerns. Castle DynamicProxy (used by Scrutor, AutoFac, and testing libraries) generates runtime proxies for AOP.
What Is the Factory Method Pattern Versus Abstract Factory?
Factory Method defines an interface for creating an object but lets subclasses decide which class to instantiate. The creator class has an abstract or virtual method that returns a product. In .NET, DbProviderFactory is a textbook Factory Method โ different providers override CreateConnection().
Abstract Factory provides an interface for creating families of related objects without specifying concrete classes. It is a factory of factories. A UI toolkit that can create Windows-style controls or Mac-style controls without the application knowing the underlying platform is a classic example.
In ASP.NET Core, IHttpClientFactory is closer to Abstract Factory โ it creates configured HttpClient instances with pre-applied DelegatingHandler pipelines, letting you produce named or typed clients without exposing the construction details.
When to use which: Factory Method when one object type varies. Abstract Factory when a family of related objects must be consistent with each other.
How Does the Command Pattern Apply in CQRS?
The Command pattern encapsulates a request as an object, enabling parameterisation of requests, queueing, logging, and undoable operations.
In CQRS architectures built with MediatR, every IRequest<T> is a Command or Query object. The separation is: Commands mutate state (create, update, delete) and return only a success/failure result. Queries read state and return data without side effects.
The Command pattern enables:
Audit logging โ commands carry all context needed to log who did what
Queuing โ commands are serialisable, so they can be dispatched to a message bus
Undo โ storing executed commands enables reversal
Pipeline enrichment โ MediatR behaviours wrap command handling with cross-cutting concerns (validation, caching, transactions) using Chain of Responsibility
At the senior level, you are expected to articulate the trade-offs: MediatR adds indirection, which makes code navigation harder and can obscure the call graph. For simple CRUD services, the overhead may not be justified.
Advanced Design Pattern Questions
How Do You Apply the Observer Pattern in a .NET Microservices Architecture?
The Observer pattern defines a one-to-many dependency between objects. When the subject's state changes, all registered observers are notified automatically. In monolithic .NET applications, INotificationHandler<T> in MediatR is an in-process Observer.
At the microservices level, the Observer pattern is implemented via an event bus. The publishing service publishes domain events (subject). Subscribing services (observers) react asynchronously via MassTransit consumers, NServiceBus handlers, or direct broker subscriptions.
The critical distinction for a senior interview: in-process observers (MediatR INotificationHandler) are synchronous or pseudo-async within the same transaction boundary. Out-of-process observers (message bus) are asynchronous and introduce eventual consistency. Choosing between them depends on whether you need transactional consistency within the observer or are willing to accept at-least-once delivery and idempotency requirements.
What Is the Specification Pattern and When Is It Useful in .NET?
The Specification pattern encapsulates a business rule as an object that can evaluate whether an entity satisfies the rule. Specifications are composable โ you can combine them with And, Or, and Not.
In .NET, Specifications are often implemented as expression trees (Expression<Func<T, bool>>) so they translate to SQL via EF Core. A CustomerIsActiveSpecification and CustomerHasPendingOrderSpecification can be combined into a composite specification without embedding the query logic in the repository.
When it's useful: complex domain query rules that must be composable, reused across queries and in-memory validation, and testable independently. When it's overkill: simple CRUD data access where a plain LINQ query is more readable.
How Does the Chain of Responsibility Pattern Manifest in ASP.NET Core?
Chain of Responsibility passes a request along a chain of handlers, where each handler decides to process it or pass it on.
In ASP.NET Core this appears in three layers:
Middleware pipeline โ each middleware either handles the request or calls
next()to pass it down the chainMediatR pipeline behaviours โ
IPipelineBehavior<TRequest, TResponse>wraps handlers; each behaviour callsnext()to invoke the next in chainDelegatingHandler in HttpClient โ each handler in the
IHttpClientFactorypipeline processes the outgoing request or passes it to the inner handler
At the senior level, you are expected to know that the order of registration matters in all three contexts โ and that short-circuiting (not calling next) is a valid and intentional pattern for authentication, rate limiting, and input validation.
What Design Pattern Underlies the Options Pattern in ASP.NET Core?
The Options Pattern (IOptions<T>, IOptionsSnapshot<T>, IOptionsMonitor<T>) is a combination of patterns:
Builder โ
services.Configure<MyOptions>()builds the configuration object from multiple sources (appsettings.json, environment variables, code)Decorator โ
IOptionsSnapshotwrapsIOptionsto provide per-request snapshots;IOptionsMonitorwraps it further with change notificationObserver โ
IOptionsMonitor<T>.OnChange()notifies registered callbacks when configuration reloads
Understanding this composition is what separates a candidate who memorises the API from one who understands its design. When you can say "the Options Pattern is a Builder composing with Decorator and Observer", you demonstrate pattern fluency rather than API recall.
How Should You Prepare for Design Pattern Questions at the Senior Level?
The most common mistake is preparing GoF patterns as isolated definitions. Interviewers at senior level are testing three things:
Can you recognise patterns in existing frameworks? (Middleware = Decorator, MediatR = Mediator + Chain of Responsibility, IHttpClientFactory = Proxy)
Can you select the right pattern for a given problem? (Strategy for swappable algorithms, Observer for event propagation, Specification for composable queries)
Can you articulate trade-offs? (Repository over EF Core vs direct DbContext; Singleton thread safety vs Scoped isolation; MediatR indirection cost)
Practise walking through the ASP.NET Core pipeline from the framework's perspective. Identify every pattern the framework uses. Then practise explaining your own codebase in pattern terms.
โ Prefer a one-time tip? Buy us a coffee โ every bit helps keep the content coming!
Frequently Asked Questions
What design patterns are most commonly asked about in senior .NET developer interviews?
The most frequently tested patterns in senior .NET interviews are Singleton (DI lifetime and thread safety), Repository (with and without EF Core), Strategy (interchangeable behaviours), Decorator (middleware and service wrapping), and Command (CQRS with MediatR). Interviewers also commonly probe the Observer pattern in the context of domain events and message buses, and the Chain of Responsibility in middleware and pipeline behaviour contexts.
Is it important to know GoF pattern names, or just the concepts?
Both matter. Using the correct pattern name signals professional literacy โ "I used the Decorator pattern here" immediately communicates intent to any senior developer. However, rattling off names without explaining why you chose a pattern, what trade-offs it introduces, and how it applies to your specific stack signals only surface-level preparation. The strongest answers pair the name with a concrete example from the framework or a production scenario.
How does SOLID relate to design patterns in C# interviews?
SOLID principles are often asked alongside design patterns because patterns are typically the implementation expression of SOLID:
Single Responsibility โ each pattern isolates one concern (Strategy isolates the algorithm; Repository isolates data access)
Open/Closed โ Decorator and Strategy allow extension without modification
Liskov Substitution โ all patterns that use polymorphism depend on LSP to function correctly
Interface Segregation โ small, focused interfaces make patterns like Adapter and Proxy easier to implement
Dependency Inversion โ patterns like Factory and Mediator invert dependencies; DI containers enforce DIP at the application level
Should you use design patterns in all ASP.NET Core projects?
No, and saying so demonstrates senior judgement. Design patterns solve recurring design problems, but they introduce indirection and abstraction that have a real cognitive cost. A small internal API with three endpoints does not need CQRS and MediatR โ it needs straightforward, readable code. Senior developers apply patterns where the complexity of the problem justifies the complexity of the solution. Over-engineering with patterns is itself an anti-pattern ("Patternitis").
How do you handle questions about anti-patterns in a .NET interview?
Anti-patterns are patterns that appear useful but cause more harm than good. Senior interviewers may ask about:
Anemic Domain Model โ placing all business logic in services rather than the domain entities, violating object-oriented principles
God Object โ a class or service that knows too much and does too much, violating Single Responsibility
Service Locator โ calling the DI container directly from application code rather than using constructor injection, hiding dependencies
Premature Abstraction โ adding interfaces and factories before you have a second implementation, creating complexity without benefit
Blob Repository โ adding every query method into one giant repository class rather than scoping repositories to aggregate roots
Acknowledging anti-patterns you have encountered in real codebases โ and explaining how you refactored away from them โ is a strong signal of genuine senior-level experience.
What is the difference between the Mediator pattern and the Event Bus pattern?
The Mediator pattern centralises communication between components in-process. MediatR is a Mediator: commands and queries are dispatched to handlers within the same process, within the same request scope, synchronously or asynchronously within that scope.
The Event Bus pattern (or Message Bus) externalises communication between services out-of-process. MassTransit and NServiceBus implement event buses: events are serialised, published to a broker (RabbitMQ, Azure Service Bus, Kafka), and consumed by separate services asynchronously. The key distinction is the transaction boundary โ Mediator can participate in the same database transaction; event bus consumers typically cannot and must handle idempotency and at-least-once delivery separately.






