HireHireInterview Quizzes › .NET Developer

.NET Developer Interview Questions

Think you're ready? These are the questions that actually decide .NET Developer interviews. Warm up on Easy — then face the Hard round, where 95% of candidates crumble. 30 questions across 3 levels, instant score, completely free.

30Questions
3Difficulty levels
95%Fail the hard round
FreeInstant score
Easy
Warm-up · 10 Qs
Medium
Practical · 10 Qs
Hard
Brutal · 10 Qs
⚡ Take the .NET Developer quiz — get your score →

The .NET Developer interview questions

Below are the real questions, grouped by difficulty. Expand any one to reveal the correct answer and why — or take the timed quiz for a score you can share. Can you clear the Hard round?

Easy round 10 questions

In C#, what is the primary difference between a value type and a reference type?
  • A. Value types are stored on the heap; reference types on the stack
  • B. Value types hold their data directly; reference types hold a reference to data on the heap ✓
  • C. Value types cannot be passed to methods; reference types can
  • D. Value types are always immutable; reference types are always mutable
Correct answer: B. A value type variable contains the actual data, while a reference type variable holds a reference (pointer) to an object allocated on the managed heap.
What does the 'using' statement in C# (e.g., using(var conn = ...)) primarily ensure?
  • A. The object is garbage collected immediately after the block
  • B. Dispose() is called on the object when the block exits, even if an exception occurs ✓
  • C. The object cannot be reassigned inside the block
  • D. The object is loaded into a static namespace scope
Correct answer: B. The using statement guarantees that Dispose() is called on an IDisposable object when control leaves the block, releasing unmanaged resources deterministically.
In ASP.NET Core, which service lifetime creates a single instance shared across the entire application?
  • A. Transient
  • B. Scoped
  • C. Singleton ✓
  • D. Request
Correct answer: C. A Singleton lifetime creates one instance that is reused for every request and injection throughout the application's lifetime.
What keyword combination is used to define an asynchronous method in C# that can be awaited?
  • A. async and await ✓
  • B. yield and return
  • C. lock and Monitor
  • D. volatile and Task
Correct answer: A. An async method is marked with the async modifier and uses await to asynchronously wait on Tasks without blocking the calling thread.
In Entity Framework Core, what does 'lazy loading' mean?
  • A. All related data is loaded upfront in a single query
  • B. Related data is loaded automatically from the database only when the navigation property is first accessed ✓
  • C. Data is cached in memory and never refreshed
  • D. Queries are deferred until SaveChanges is called
Correct answer: B. Lazy loading defers loading of related entities until the navigation property is actually accessed, triggering a separate database query at that point.
What is the correct way to declare a nullable value type (e.g., an integer that can be null) in C#?
  • A. nullable int x;
  • B. int? x; ✓
  • C. int@ x;
  • D. null int x;
Correct answer: B. The '?' suffix (int?) is shorthand for Nullable<int>, allowing a value type to also hold null.
In a RESTful ASP.NET Core Web API, which HTTP status code should be returned when a newly created resource succeeds?
  • A. 200 OK
  • B. 201 Created ✓
  • C. 204 No Content
  • D. 302 Found
Correct answer: B. 201 Created indicates a request has succeeded and a new resource was created, typically returned with a Location header pointing to it.
What does the 'virtual' keyword allow when applied to a method in a C# base class?
  • A. It prevents the method from being called externally
  • B. It allows derived classes to override the method's implementation ✓
  • C. It makes the method static across all instances
  • D. It forces the method to run asynchronously
Correct answer: B. A virtual method provides a default implementation that derived classes may override using the override keyword, enabling polymorphism.
Which statement about the C# garbage collector (GC) is correct?
  • A. It frees managed heap memory automatically for objects no longer reachable ✓
  • B. It must be manually triggered for every object
  • C. It releases unmanaged resources like file handles automatically
  • D. It runs only when the application exits
Correct answer: A. The .NET GC automatically reclaims managed heap memory occupied by objects that are no longer reachable by the application.
In ASP.NET Core middleware, what is the significance of the order in which middleware components are added to the pipeline?
  • A. Order has no effect; all run in parallel
  • B. Order determines the sequence in which requests and responses are processed ✓
  • C. Only the last middleware added is executed
  • D. Middleware order affects only logging, not functionality
Correct answer: B. Middleware executes in the order it is registered for the request path and in reverse order for the response, so ordering is functionally critical.

Medium round 10 questions

You have a method that queries a database and you want the calling thread to remain responsive without blocking while awaiting the result. Which approach is correct?
  • A. Mark the method async and use await on the asynchronous database call, returning Task or Task<T> ✓
  • B. Call the database method and immediately call .Result to unwrap the value
  • C. Wrap the call in a new Thread and join it before returning
  • D. Mark the method async void and await inside it
Correct answer: A. Making the method async and awaiting the async call returns a Task/Task<T> and avoids blocking, while async void should be reserved for event handlers and .Result can deadlock.
In ASP.NET Core, which service lifetime creates a single instance per HTTP request, shared across all components handling that request?
  • A. Transient
  • B. Scoped ✓
  • C. Singleton
  • D. Instanced
Correct answer: B. Scoped services are created once per client request (scope), whereas Transient creates a new one each time and Singleton lives for the app's lifetime.
Using Entity Framework Core, you load a list of orders and access order.Customer.Name in a loop, triggering a separate query per order. What is this problem commonly called and how is it typically fixed?
  • A. N+1 query problem; fix with eager loading via .Include(o => o.Customer) ✓
  • B. Deadlock; fix by adding a transaction scope
  • C. Connection leak; fix by disposing the DbContext sooner
  • D. Cartesian explosion; fix by adding AsNoTracking()
Correct answer: A. Lazy-loading a related entity inside a loop causes the N+1 query problem, resolved by eager loading the related data with .Include.
What is the primary difference between IEnumerable<T> and IQueryable<T> when working with a database via LINQ?
  • A. IQueryable executes the query in the database, while IEnumerable pulls data into memory and filters client-side ✓
  • B. IEnumerable is strongly typed while IQueryable is not
  • C. IQueryable only works with arrays; IEnumerable works with any collection
  • D. There is no practical difference; they are interchangeable
Correct answer: A. IQueryable builds an expression tree translated to SQL and executed on the server, whereas IEnumerable materializes results and applies operations in memory.
In a Web API controller, you need to return a 404 when a requested resource is not found. Which is the idiomatic approach in ASP.NET Core?
  • A. return NotFound(); ✓
  • B. throw new Exception("404");
  • C. return StatusCode(200, null);
  • D. Response.StatusCode = 404; return null;
Correct answer: A. NotFound() is the built-in helper that returns an HTTP 404 result cleanly from a controller action.
Which statement about async/await deadlocks is correct when calling async code from a synchronous context?
  • A. Blocking on an async call with .Result or .Wait() can deadlock when the captured synchronization context is needed to resume the continuation ✓
  • B. await always deadlocks unless ConfigureAwait(true) is used
  • C. Deadlocks only occur in multi-threaded console apps, never in web apps
  • D. Using Task.Run inside every async method prevents all deadlocks
Correct answer: A. Blocking synchronously on a Task can deadlock because the continuation needs the same context that is blocked waiting; using async all the way (or ConfigureAwait(false)) avoids it.
You want to guarantee an object like a database connection is disposed even if an exception is thrown. Which is the recommended C# construct?
  • A. A using statement (or using declaration) around the disposable object ✓
  • B. A try/catch that logs the exception
  • C. Calling GC.Collect() after using the object
  • D. Setting the object to null when done
Correct answer: A. The using statement ensures Dispose() is called via a try/finally under the hood, even when exceptions occur.
In dependency injection, why is it generally preferred to depend on an interface (e.g., IRepository) rather than a concrete class in your service constructors?
  • A. It decouples the consumer from the implementation, enabling easier testing (mocking) and swapping implementations ✓
  • B. Interfaces execute faster than concrete classes at runtime
  • C. Concrete classes cannot be registered in the DI container
  • D. Interfaces automatically make the class thread-safe
Correct answer: A. Programming to an interface enables loose coupling so implementations can be substituted or mocked in unit tests without changing consumers.
What does the async keyword do when applied to a method that contains no await expression?
  • A. The method runs synchronously and the compiler warns that it will run synchronously ✓
  • B. The method automatically runs on a background thread
  • C. It causes a compile-time error
  • D. It makes the method non-blocking regardless of its body
Correct answer: A. Without an await, the async method executes synchronously and the compiler emits a warning (CS1998) since there is nothing to await.
In EF Core, when should you use AsNoTracking() on a query?
  • A. For read-only queries where you don't intend to update the returned entities, to improve performance ✓
  • B. Whenever you plan to modify and save the entities back to the database
  • C. Only inside a transaction to prevent dirty reads
  • D. To force EF to reload navigation properties on every access
Correct answer: A. AsNoTracking skips setting up change tracking, which improves performance and memory use for read-only scenarios where updates aren't needed.

Hard round 10 questions

A synchronous ASP.NET Core MVC action (running under the default request context in a legacy self-hosted scenario with a SynchronizationContext) calls `var data = GetDataAsync().Result;`. Inside `GetDataAsync`, an `await httpClient.GetStringAsync(url)` is used without `ConfigureAwait(false)`. The request hangs forever. What is the precise root cause?
  • A. The HttpClient instance is not thread-safe and blocks its own connection pool
  • B. The awaited continuation is posted back to the captured SynchronizationContext, whose only thread is already blocked on .Result waiting for that continuation ✓
  • C. GetStringAsync internally uses a ThreadPool thread that is exhausted by the blocking call
  • D. .Result throws an AggregateException that is silently swallowed, leaving the task incomplete
Correct answer: B. The await captures the single-threaded context; the continuation is queued to a thread that is blocked on .Result, so neither can proceed — ConfigureAwait(false) avoids capturing the context and breaks the deadlock.
Consider: `var actions = new List<Func<int>>(); for (int i = 0; i < 3; i++) actions.Add(() => i); Console.WriteLine(string.Join(",", actions.Select(a => a())));` in C# 4.0 semantics (pre-C# 5 foreach fix, classic for loop). What is printed?
  • A. 0,1,2
  • B. 3,3,3 ✓
  • C. 0,0,0
  • D. 2,2,2
Correct answer: B. A `for` loop's counter `i` is a single variable captured by reference by all closures, so after the loop each lambda reads the final value 3 — unlike `foreach`, which since C# 5 declares a fresh variable per iteration.
You register `IClock` (a Scoped service that reads a per-request tenant id) and inject it into a Singleton `CacheWarmer`. In production the warmer intermittently serves data for the wrong tenant. What is the correct explanation and fix?
  • A. Scoped services are thread-unsafe by design; wrap IClock access in a lock
  • B. The Singleton captured the first request's scoped IClock instance (captive dependency); inject IServiceScopeFactory and resolve IClock inside a created scope per operation ✓
  • C. Scoped lifetime is invalid for interfaces; re-register IClock as Transient to get a fresh instance each call
  • D. The DI container leaks the scope; call GC.Collect() after each request to release it
Correct answer: B. A Singleton resolving a Scoped dependency captures it once for the app's lifetime (the captive dependency problem); the fix is to inject IServiceScopeFactory and create a scope per unit of work.
This EF Core query loops `foreach (var o in ctx.Orders.ToList()) { total += o.Customer.Name.Length; }` with lazy loading enabled. Against 1,000 orders it issues 1,001 database round trips. Which single change eliminates the N+1 without changing tracked results?
  • A. Add `.AsNoTracking()` to the Orders query
  • B. Replace `.ToList()` with `.AsEnumerable()` to stream results
  • C. Use `ctx.Orders.Include(o => o.Customer).ToList()` so Customer is loaded in the same query ✓
  • D. Wrap the loop in a single explicit transaction with Serializable isolation
Correct answer: C. Each `o.Customer` access triggers a separate lazy-load query (the N+1); `Include` eager-loads Customer in the original query, collapsing 1,001 round trips into one.
A payment service receives the same 'charge $50' message twice due to at-least-once broker delivery. To make the handler idempotent so the customer is charged once, which design is correct and race-safe under concurrent duplicate delivery?
  • A. Check `SELECT` for an existing charge with the same idempotency key, then `INSERT` if absent — in two separate statements
  • B. Persist the charge with the client-supplied idempotency key under a UNIQUE constraint in the same transaction as the charge, treating a duplicate-key violation as 'already processed' ✓
  • C. Add a 5-second in-memory dedup cache of recently seen message ids on each service instance
  • D. Configure the broker for exactly-once delivery so the handler needs no idempotency logic
Correct answer: B. A non-atomic check-then-insert has a TOCTOU race under concurrency; a UNIQUE constraint on the idempotency key committed atomically with the charge lets the database enforce single-charge semantics, and exactly-once broker delivery is generally unattainable end-to-end.
In an ASP.NET Core pipeline, a developer writes `app.UseRouting(); app.UseEndpoints(...); app.UseAuthorization();` (authorization added AFTER endpoints). Requests to `[Authorize]` endpoints succeed even when unauthenticated. Why?
  • A. UseAuthorization only works with cookie auth, not JWT bearer
  • B. The authorization middleware is registered after the endpoint has already executed, so its policy check never runs for the matched endpoint ✓
  • C. Endpoint routing disables all middleware ordering, so position is irrelevant
  • D. UseAuthorization must be called before UseRouting to build the endpoint graph
Correct answer: B. Middleware runs in registration order; placing UseAuthorization after the endpoint execution means the terminal endpoint handles the request before the authorization check can enforce the policy.
Under sudden load, a service that does `httpClient.GetAsync(...).GetAwaiter().GetResult()` on every request sees requests time out and thread count climb, even though CPU is near-idle. What is happening?
  • A. Thread pool starvation: each request blocks a pool thread on I/O, the pool grows only ~1 thread/500ms, so incoming work queues faster than threads are injected ✓
  • B. The garbage collector is pausing all threads in a Gen 2 full collection under load
  • C. HttpClient's connection pool is exhausted, forcing synchronous DNS lookups on each call
  • D. The CLR is JIT-recompiling the hot path repeatedly, consuming threads
Correct answer: A. Sync-over-async blocks a thread pool thread for the whole I/O duration; the pool injects new threads slowly, so under load the queue outpaces thread injection — classic thread pool starvation despite idle CPU.
You have `struct Point { public int X; public void Inc() => X++; }` and store instances in a `List<Point>`. Calling `myList[0].Inc()` does not change the stored value, but calling `Inc()` on a `Point[]` element via `myArray[0].Inc()` does. Why the difference?
  • A. List<T> boxes value types on insertion, so Inc mutates a boxed copy
  • B. List<T>'s indexer returns a copy of the struct (a method call), while an array element access returns a direct reference to the element ✓
  • C. Arrays store structs by reference while List<T> stores them by value
  • D. The array version also fails; both leave the original unchanged
Correct answer: B. `List<T>`'s indexer is a property returning a by-value copy that Inc mutates and discards, whereas array indexing yields a direct addressable location so the in-place mutation sticks — a well-known mutable-struct trap.
A method returns `ValueTask<int>`. A caller writes `var vt = obj.ComputeAsync(); int a = await vt; int b = await vt;` where the implementation pools its IValueTaskSource. What is the correct assessment?
  • A. Fully safe — ValueTask is just a lightweight Task and can be awaited any number of times
  • B. Awaiting the same ValueTask twice is undefined behavior; the backing IValueTaskSource may be reset/reused, so the second await can throw or return a wrong/torn result ✓
  • C. The second await always returns the cached result with zero cost, which is the point of ValueTask
  • D. It only fails if the ValueTask wraps a Task; pooled sources are always safe to re-await
Correct answer: B. A ValueTask backed by a pooled IValueTaskSource must be consumed exactly once; the token/version can be recycled after the first await, making a second await undefined behavior.
A high-throughput producer/consumer needs bounded buffering with backpressure so fast producers block when consumers fall behind, plus native async consumption. Which primitive best fits and why over the alternatives?
  • A. `ConcurrentQueue<T>` with a busy-wait polling consumer loop for lowest latency
  • B. `Channel<T>` created bounded with `BoundedChannelFullMode.Wait`, exposing an async writer that yields on a full buffer and an IAsyncEnumerable reader ✓
  • C. `BlockingCollection<T>`, since its async support gives non-blocking backpressure out of the box
  • D. `List<T>` guarded by a single lock, resizing to absorb bursts
Correct answer: B. A bounded `Channel<T>` in Wait mode provides asynchronous, non-thread-blocking backpressure and native async reads; BlockingCollection blocks threads, ConcurrentQueue has no built-in bounding/backpressure, and a locked List is neither async nor bounded.

Prep for another role

Questions are original, written and independently verified for HireHire's role interview quizzes. They reflect the kind of knowledge .NET Developer interviews test, not any specific company's questions. HireHire maps live tech & IT jobs across India, updated regularly. Last updated: July 2026.