.NET Developer interview question
How do .NET dependency injection lifetimes differ?
Transient creates each resolution, scoped reuses one instance per request or scope, and singleton lives for the application. A singleton must not capture scoped services and shared state must be thread-safe.
Direct answer
What a strong answer covers
How it works
Transient services are constructed every time they are resolved. Scoped services are constructed once per scope, which in ASP.NET Core is one HTTP request, so a DbContext registered as scoped is shared by everything in that request and disposed at its end. Singletons are constructed once for the application. The container enforces one rule at validation time: a singleton must not depend on a scoped service, because it would capture the first request’s instance forever. Singletons must be thread-safe, and anything IDisposable is disposed by the scope that created it.
Example
A background service registered as a singleton needed the DbContext; injecting it directly failed validation at startup. The fix injected IServiceScopeFactory, created a scope per unit of work, resolved the DbContext inside it, and disposed the scope. An HttpClient wrapper was registered through IHttpClientFactory so handlers are pooled instead of exhausting sockets with a transient HttpClient.
Common mistakes
- Registering DbContext as a singleton and sharing it across threads.
- Resolving a scoped service from the root provider and never disposing it.
- Making a transient service hold expensive state such as a connection pool.
A useful answer structure
Answer from your own work.
Do not memorise a script: use only examples you can explain honestly in follow-up questions.
Open the desktop workspace and rehearse a clear answer in your own words.