377 questions for senior .NET engineer interviews, each with a 30-second answer, the full answer, a deep dive, the follow-ups interviewers ask next, and real-world production problems.
SOLID, the wider design principles (DRY, KISS, YAGNI, coupling and cohesion and more) and the senior judgement to know when to apply them.
SRP as one reason to change (one actor), spotting violations, splitting by change drivers, and avoiding over-fragmentation.
Open for extension, closed for modification; strategy, polymorphism, DI and pattern-based extension; when a switch is fine; avoiding speculative generality.
Behavioural subtyping, preconditions, postconditions and invariants, NotSupportedException smells, the read-only collection example, and fixing hierarchies.
Client-specific interfaces, fat interface smells, read and write splits, role interfaces, default interface methods and avoiding interface explosion.
High-level policy not depending on low-level details, abstraction ownership, DIP versus DI versus IoC containers, ports and adapters, and when not to invert.
Don't Repeat Yourself as single source of knowledge, not identical text; accidental versus true duplication; the wrong abstraction; where DRY matters most.
Keep It Simple: essential versus accidental complexity, simple versus easy, readable code over clever code, and how to argue for simplicity in design reviews.
You Aren't Gonna Need It: costs of building speculative features, the difference between speculative features and keeping options open, and reversible versus irreversible decisions.
Separation of Concerns at method, class, project and service level; layers versus vertical slices; cross-cutting concerns via middleware and filters; the cost of over-separation.
Cohesion as how strongly the parts of a module belong together; types of cohesion; symptoms such as utility classes and feature envy; measuring with LCOM; refactoring by feature.
Coupling as the degree of dependency between modules; types from content to data coupling; temporal, deployment and database coupling in distributed systems; techniques to reduce it.
Principle of least knowledge: talk only to immediate collaborators; train-wreck chains; why fluent builders and LINQ are not violations; refactoring by moving behaviour.
Tell objects what to do instead of querying state and deciding outside; anaemic versus rich models; invariants; where querying is fine (CQRS reads, DTOs).
Detect invalid state at the earliest point: guard clauses, ArgumentNullException.ThrowIfNull, options validation on start, ValidateOnBuild; fail fast versus resilience at boundaries.
Code and APIs should behave as users expect: naming, side effects, .NET conventions (Try pattern, Async suffix, CancellationToken last), equality, exceptions and defaults.
Sensible defaults that remove boilerplate: EF Core key and relationship conventions, ASP.NET Core routing and configuration conventions; overriding defaults; risks of hidden magic.
Costs of abstraction, the one-implementation interface debate, test seams versus speculative layers, leaky abstractions over EF Core and HttpClient, and criteria for adding or removing an abstraction.
Rule of three, the wrong abstraction, duplication across bounded contexts and services, test code, and how to justify keeping duplication to reviewers.
Signals of over-engineering (layers, patterns, microservices, configurability), metrics to prove it, communicating with the team, and incremental simplification.
Refactoring strategy: characterisation tests, strangler fig, branch by abstraction, parallel change, feature flags, small pull requests, measuring progress, and when to stop.