🔷

Top 50 .NET & C# Interview Questions with Real Examples

A curated set of 50 high-frequency .NET and C# interview questions with clear, production-grade answers and real-world examples. Covers C# language fundamentals, the CLR and garbage collection, OOP in C#, ASP.NET Core & MVC, REST Web API, Entity Framework, LINQ and design patterns — for .NET developer and full-stack interviews.

50questions
7categories
10beginner
27intermediate
13advanced
Showing 50 of 50 questions

💎 C# Language (13)

Q7.What's the difference between value types and reference types in C#?Beginner

Value types (int, double, bool, struct, enum) hold their data directly and are typically stored on the stack (or inline in the containing object); assigning one copies the value. Reference types (class, string, array, object, delegate) hold a reference to data on the managed heap; assigning copies the reference, so both variables point to the same object. This is the root of most 'why did my object change?' bugs.

💡 Real-life example

📋 struct Point copied → two independent points. class Person copied → two variables, ONE person; editing via one is visible through the other.

Q8.What is boxing and unboxing in C#?Intermediate

Boxing wraps a value type in an object on the heap so it can be treated as a reference type (e.g., assigning an int to object). Unboxing extracts the value type back out, with a runtime type check and a copy. Both have performance and allocation cost. Generics (List<int> instead of ArrayList) and avoiding object parameters eliminate most boxing.

💡 Real-life example

📦 `object o = 42;` boxes the int onto the heap. `int x = (int)o;` unboxes it. In a tight loop, boxing millions of ints creates GC pressure — use List<int>, not ArrayList.

Q9.What's the difference between const and readonly in C#?Beginner

const is a compile-time constant — its value is baked into callers at compile time and must be a literal known then; it's implicitly static. readonly is a runtime constant — assigned at declaration or in the constructor, so it can be computed or differ per instance, and it can hold reference types. Rule: use const for true compile-time literals (Pi, MaxRetries); use readonly for values fixed at construction.

💡 Real-life example

🔒 `const double Pi = 3.14159;` (compile-time). `readonly DateTime CreatedAt = DateTime.Now;` (set once at runtime in the constructor — a const couldn't do this).

Q10.What's the difference between ref and out parameters in C#?Intermediate

Both pass arguments by reference so the method can modify the caller's variable. ref requires the variable to be initialized before the call and the method may read it. out does NOT require prior initialization and the method MUST assign it before returning — used for returning extra values. Modern C# also has `in` (pass by reference, read-only).

💡 Real-life example

🔄 `int.TryParse("42", out int n)` — out returns the parsed value (no need to init n first). ref is for in-and-out: `void Double(ref int x) { x *= 2; }`.

Q11.What's the difference between string and StringBuilder in C#?Beginner

string is immutable — every modification creates a new string object. Concatenating in a loop with + creates many temporary strings (O(n²) and heavy GC). StringBuilder is a mutable buffer; appending modifies it in place (amortized O(n)). Use string for a few fixed concatenations; use StringBuilder when building strings in loops or with many appends.

💡 Real-life example

🧵 Building a 10,000-line report: `+` in a loop allocates thousands of throwaway strings. A StringBuilder appends into one growing buffer — dramatically faster, far less GC.

Q12.What's the difference between var, dynamic and object in C#?Intermediate

var is compile-time type inference — the type is fixed at compile time, fully type-checked, just less verbose. object is the base type of everything — strongly typed but you must cast to use members (boxing for value types). dynamic bypasses compile-time checking entirely; member resolution happens at runtime (DLR), so typos compile but throw at runtime. Prefer var; use dynamic only for interop (COM, JSON, reflection-heavy code).

💡 Real-life example

🎯 `var x = 5;` → x is int, checked now. `object o = 5;` → must cast to use as int. `dynamic d = 5; d.Foo();` → compiles, throws RuntimeBinderException at runtime.

Q13.What is the difference between IEnumerable and IQueryable in LINQ?Intermediate

IEnumerable<T> executes queries in-memory (LINQ to Objects) — data is fetched first, then filtering/sorting happens in your process. IQueryable<T> builds an expression tree that the provider (e.g., Entity Framework) translates to a backend query (SQL) so filtering happens at the database. For DB work use IQueryable so `Where`/`Take` run as SQL; switching to IEnumerable too early pulls the whole table into memory.

💡 Real-life example

🗃️ `db.Users.Where(u => u.Active).Take(10)` on IQueryable → `SELECT TOP 10 ... WHERE Active=1` runs in SQL. Call `.AsEnumerable()` first and you'd download every user, then filter in C#.

Q14.What's the difference between IEnumerable and List in C#?Beginner

IEnumerable<T> is a read-only, forward-only abstraction for iterating a sequence — it may be lazily evaluated and doesn't expose Count or indexing. List<T> is a concrete, in-memory, indexable, mutable collection (Add/Remove/[]), and is itself an IEnumerable. Accept IEnumerable<T> in method parameters for flexibility; return/use List<T> when you need indexing, Count, or to materialize results once.

💡 Real-life example

📚 A method `Process(IEnumerable<Order> orders)` accepts arrays, lists or LINQ queries. If you need `orders.Count` or `orders[0]`, materialize with `.ToList()` first to avoid re-enumerating.

Q15.What are extension methods in C#?Intermediate

Extension methods let you add methods to an existing type (even sealed types or interfaces you don't own) without modifying it or subclassing. They are static methods in a static class whose first parameter is prefixed with `this`. The compiler lets you call them as if they were instance methods. The entire LINQ API (Where, Select, etc.) is extension methods on IEnumerable<T>.

💡 Real-life example

🔧 `public static bool IsNullOrEmpty(this string s) => string.IsNullOrEmpty(s);` lets you write `name.IsNullOrEmpty()` — looks like a String method but it's yours.

Q16.What's the difference between a delegate and an event in C#?Advanced

A delegate is a type-safe function pointer — a variable that holds a reference to one or more methods. An event is a restricted wrapper around a delegate that only allows += (subscribe) and -= (unsubscribe) from outside the declaring class; subscribers can't invoke it or overwrite other subscribers. Events implement the publish-subscribe pattern safely; Action/Func are common delegate types.

💡 Real-life example

📡 A Button exposes `event EventHandler Click`. Outside code can subscribe (+=) but cannot raise the click or clear everyone else's handlers — only the Button raises it. A raw delegate would allow both, which is unsafe.

Q17.What is async/await and how does it work in C#?Advanced

async/await enables non-blocking asynchronous code that reads like synchronous code. An async method returns Task/Task<T> (or ValueTask). await suspends the method at an awaited operation, returns the thread to the pool, and resumes when the operation completes — so threads aren't blocked waiting on I/O. It improves scalability (more requests per thread), not raw speed. Use it for I/O (DB, HTTP, files); avoid async void except for event handlers.

💡 Real-life example

⏳ `var data = await httpClient.GetStringAsync(url);` — while the HTTP call is in flight, the thread serves other requests instead of blocking. On a web server this multiplies throughput.

Q18.What's the difference between Convert.ToString() and .ToString()?Intermediate

.ToString() throws a NullReferenceException if the object is null, because you're calling an instance method on null. Convert.ToString() is null-safe — it returns an empty string (or null for the nullable overload) instead of throwing. For known non-null values both are equivalent; Convert.ToString() is safer when the value might be null.

💡 Real-life example

🛡️ `object o = null; o.ToString();` → NullReferenceException. `Convert.ToString(o);` → returns "" safely. Use Convert.ToString() (or the null-conditional `o?.ToString()`) for possibly-null values.

Q19.What are mutable and immutable types in C#? Give examples.Intermediate

A mutable object's state can change after creation (e.g., List<T>, StringBuilder, a class with public setters). An immutable object's state can't change once constructed (e.g., string, record types, a class with only readonly/init-only fields). Immutability gives thread safety (shareable without locks), predictability, and safe use as dictionary keys. C# `record` types and `init`-only setters make immutability easy.

💡 Real-life example

🔒 `string` is immutable — `s.Replace(...)` returns a new string. A `record Person(string Name)` is immutable; to 'change' it you create a copy: `p with { Name = "Bo" }`.

⚙️ .NET & CLR Internals (6)

Q1.What is the CLR (Common Language Runtime) in .NET?Beginner

The CLR is the execution engine of .NET. It runs your compiled code and provides core services: JIT compilation of IL to native code, automatic memory management (garbage collection), type safety, exception handling, security, and thread management. Any .NET language (C#, F#, VB) compiles to a common Intermediate Language (IL/MSIL) that the CLR executes — which is why they interoperate.

💡 Real-life example

⚙️ Like the JVM for Java: you write C#, the compiler emits IL, and the CLR turns that IL into machine code for the actual CPU at runtime — handling memory and safety so you don't have to.

Q2.What is the JIT compiler and how does it work in .NET?Intermediate

The Just-In-Time (JIT) compiler converts IL (Intermediate Language) into native machine code at runtime, method by method, the first time each method is called. Variants: standard JIT (compiles on demand), and Tiered Compilation (a quick tier first for fast startup, then a fully optimized tier for hot methods). AOT/ReadyToRun can precompile to cut startup cost.

💡 Real-life example

🔥 A method called once gets a fast, lightly-optimized compile; a method called millions of times gets re-JITted with aggressive optimizations — best of both startup and throughput.

Q3.Explain garbage collection and generations in .NET.Intermediate

The .NET GC automatically reclaims managed heap memory no longer referenced. It's generational: Gen 0 (new, short-lived objects — collected often and cheaply), Gen 1 (survivors — a buffer), and Gen 2 (long-lived objects — collected rarely). Large objects (≥85 KB) go on the Large Object Heap (LOH). Most objects die young, so collecting Gen 0 frequently is efficient. You don't free memory manually, but you must Dispose unmanaged resources.

💡 Real-life example

♻️ A temporary string in a loop dies in Gen 0 within milliseconds. A cached service lives in Gen 2 for the app's lifetime. Calling GC.Collect() manually is almost always wrong — let the GC decide.

Q4.What's the difference between managed and unmanaged code?Intermediate

Managed code runs under the CLR, which provides garbage collection, type safety and security (e.g., C#). Unmanaged code runs directly on the OS with no CLR services — you manage memory yourself (e.g., C/C++, Win32 APIs, COM). When managed code calls unmanaged resources (file handles, DB connections, native libraries via P/Invoke), you must release them explicitly with Dispose/using because the GC doesn't track them.

💡 Real-life example

🔌 A SqlConnection wraps an unmanaged native handle. The GC frees the managed wrapper, but you must Dispose() (or use a `using`) to release the underlying unmanaged connection promptly.

Q5.What's the difference between .NET Framework, .NET Core and modern .NET (.NET 5+)?Intermediate

.NET Framework is the original Windows-only platform (legacy, max version 4.8). .NET Core is the cross-platform, open-source, high-performance rewrite. Since .NET 5 they unified into just '.NET' (one cross-platform runtime, current is .NET 8/9). .NET Standard was a shared API spec so libraries could target both worlds — now largely obsolete since everything converged on .NET. New projects should target modern .NET.

💡 Real-life example

🪟 Legacy enterprise app stuck on Windows? .NET Framework 4.8. New microservice on Linux containers? .NET 8. The performance gap is huge — modern .NET is several times faster.

Q6.What is an assembly in .NET, and how does it differ from a class library?Advanced

An assembly is the unit of deployment, versioning and security in .NET — a compiled .dll or .exe containing IL plus a manifest (metadata about types, versions and dependencies). A class library is a project type that produces a .dll assembly of reusable types with no entry point. So 'assembly' is the runtime/deployment concept; 'class library' is the project that builds one. Assemblies can be private (app folder) or shared (the GAC, in .NET Framework).

💡 Real-life example

📦 Your MyApp.Data.dll is an assembly built from a class library project. Its manifest declares it depends on EntityFrameworkCore v8.0 — the CLR uses that to load the right versions at runtime.

🏛️ OOP in C# (7)

Q20.What are the four pillars of OOP, and how does C# implement them?Beginner

Encapsulation — hide state behind access modifiers and properties (private fields + public getters/setters). Inheritance — derive classes with `: BaseClass`. Polymorphism — virtual/override for runtime, overloading for compile-time. Abstraction — abstract classes and interfaces expose 'what' while hiding 'how'. Together they enable modular, reusable, maintainable code. For pure OOP depth see our OOP interview set.

💡 Real-life example

🏛️ A `BankAccount` encapsulates `balance` (private), is inherited by `SavingsAccount`, overrides `CalculateInterest()` (polymorphism), and implements an `IAccount` interface (abstraction).

Q21.What's the difference between method overloading and overriding in C#?Intermediate

Overloading: multiple methods with the same name but different parameter lists in the same class — resolved at COMPILE time (static binding). Overriding: a derived class redefines a base method marked virtual/abstract using the override keyword — resolved at RUNTIME (dynamic dispatch) based on the object's actual type. Overloading is compile-time polymorphism; overriding is runtime polymorphism.

💡 Real-life example

🎭 `Area(int)` and `Area(int,int)` = overloading (compiler picks by args). `Shape` has `virtual Draw()`; `Circle` `override Draw()` = overriding (runtime picks Circle's version even through a Shape reference).

Q22.Explain virtual, override and new in C#. What does this print: A a = new C(); a.foo();?Advanced

virtual marks a base method as overridable; override replaces it with runtime dispatch; new HIDES the base method (compile-time, based on the reference type). If A.foo is virtual and B and C override it, then `A a = new C(); a.foo();` prints "C" — runtime dispatch follows the actual object (C). But if foo is NON-virtual (plain methods, hidden via new), `a.foo()` prints "A" — it binds to the reference type A at compile time. This exact trick is a classic .NET interview question.

💡 Real-life example

🔀 virtual+override chain A→B→C, `A a=new C(); a.foo()` → "C" (dynamic dispatch). Non-virtual same hierarchy → "A" (the reference type A decides). The keyword virtual is what flips the behavior.

Q23.What's the difference between an abstract class and an interface in C#?Intermediate

An abstract class can have state (fields), constructors, and both abstract and concrete members; a class can inherit only ONE. An interface is a contract — historically members-only, but since C# 8 it can have default implementations; a class can implement MANY interfaces. Use an abstract class for a shared base with common state/behavior (is-a); use an interface to declare a capability multiple unrelated types can have (can-do).

💡 Real-life example

🧩 `abstract class Animal` with shared `Name` + abstract `Speak()`. `interface IComparable`, `IDisposable` — capabilities a class plugs in. A class can be one Animal but implement many interfaces.

Q24.What's the difference between abstraction and encapsulation?Intermediate

Abstraction is about DESIGN — exposing only essential behavior and hiding complexity (achieved with interfaces/abstract classes). Encapsulation is about IMPLEMENTATION — bundling data with methods and restricting direct access to internal state (achieved with access modifiers and properties). Abstraction = hide complexity (what); encapsulation = hide data (how). They reinforce each other.

💡 Real-life example

🚗 Abstraction: a `Drive()` method — you don't think about pistons. Encapsulation: the engine's `fuelLevel` is private, changed only through validated methods. One hides complexity, the other protects data.

Q25.What's the difference between association, aggregation and composition?Advanced

All describe 'has-a' relationships with increasing ownership. Association: objects know each other but have independent lifecycles (a Teacher and a Student). Aggregation: a 'whole' references 'parts' that can exist independently (a Department has Employees, but employees survive the department). Composition: the 'whole' owns the 'parts' and they die with it (a House has Rooms — destroy the house, the rooms are gone).

💡 Real-life example

🏠 Composition: `House` creates and owns its `Room`s — no house, no rooms. Aggregation: a `Playlist` references `Song`s that exist on their own. Association: an `Order` references a `Customer` — loosely linked.

Q26.What are the SOLID principles?Advanced

Five OOP design principles for maintainable code: S — Single Responsibility (a class has one reason to change). O — Open/Closed (open for extension, closed for modification). L — Liskov Substitution (subtypes must be usable wherever the base type is, without breaking behavior). I — Interface Segregation (many small interfaces over one fat one). D — Dependency Inversion (depend on abstractions, not concretions — the basis of DI).

💡 Real-life example

🧱 Violating L: a `Square : Rectangle` that breaks `SetWidth`/`SetHeight` independence. Following D: a controller depends on `IRepository`, not `SqlRepository` — so you can swap implementations and inject mocks in tests.

🌐 ASP.NET Core & MVC (11)

Q27.What is ASP.NET Core and how does it differ from classic ASP.NET?Beginner

ASP.NET Core is the cross-platform, open-source, high-performance framework for building web apps and APIs on modern .NET. Versus classic ASP.NET (Windows/IIS-only, System.Web): Core runs anywhere (Linux, containers), has a unified MVC + Web API + Razor Pages model, built-in dependency injection, a flexible middleware pipeline, configuration providers, and is far faster. It can self-host via Kestrel rather than requiring IIS.

💡 Real-life example

🌐 A classic ASP.NET MVC app ties you to Windows + IIS. The same app on ASP.NET Core runs in a Linux Docker container behind Kestrel, with DI and middleware built in — cheaper to host and much faster.

Q28.Explain the MVC pattern and the ASP.NET MVC request life cycle.Intermediate

MVC separates concerns: Model (data + business logic), View (UI), Controller (handles input, coordinates model and view). The ASP.NET MVC life cycle: routing maps the URL to a controller/action → controller instantiated → action filters run → action executes → it returns an ActionResult (View, JSON, Redirect) → the view engine renders → response sent. Understanding this pipeline is key to placing filters, model binding and validation correctly.

💡 Real-life example

🔄 GET /products/5 → routing → ProductsController.Details(5) → [Authorize] filter → action fetches the model → returns View(model) → Razor renders HTML → response. Each stage is an extension point.

Q29.What's the difference between convention-based and attribute routing?Intermediate

Convention-based routing defines URL patterns centrally (e.g., {controller}/{action}/{id?}) — concise for uniform apps but less explicit. Attribute routing places routes directly on controllers/actions with [Route("...")], [HttpGet("...")] — explicit, supports complex/RESTful URLs, versioning and parameter constraints per endpoint. Web APIs typically use attribute routing; you can mix both.

💡 Real-life example

🛣️ Convention: one rule handles `/products/details/5`. Attribute: `[HttpGet("api/v2/products/{id:int}")]` right on the method — explicit, versioned, with an int constraint. APIs favor attribute routing.

Q30.What's the difference between ViewData, ViewBag and TempData in ASP.NET MVC?Intermediate

All pass data from controller to view, but: ViewData is a dictionary (ViewData["x"]) — requires casting, available for the current request. ViewBag is a dynamic wrapper over ViewData (ViewBag.x) — no casting, also current request only. TempData persists across ONE subsequent request (backed by session) — ideal for passing data through a redirect (e.g., a success message after POST-redirect-GET).

💡 Real-life example

📨 After a successful form POST you redirect to a list page and show 'Saved!'. ViewData/ViewBag would be lost on redirect; `TempData["msg"]` survives exactly one redirect to display the message.

Q31.What are filters in ASP.NET MVC / Core?Intermediate

Filters inject logic into the request pipeline around action execution. Types (in order): Authorization filters (auth checks), Resource filters (caching, short-circuiting), Action filters (run before/after an action — logging, model tweaks), Exception filters (handle errors), Result filters (around result execution). They centralize cross-cutting concerns instead of repeating code in every action.

💡 Real-life example

🛡️ `[Authorize]` (authorization filter) blocks unauthenticated users. A custom `[LogActionAttribute]` action filter logs every call's duration — applied once, runs everywhere it's attached.

Q32.What is middleware in ASP.NET Core?Advanced

Middleware are components assembled into a pipeline that each handle an HTTP request and decide whether to pass it to the next component (via next()) or short-circuit. Order matters — they run top-down on the request and bottom-up on the response. Built-in middleware: routing, authentication, authorization, CORS, static files, exception handling. It's the Core replacement for HttpModules/HttpHandlers.

💡 Real-life example

🔗 `app.UseExceptionHandler()` → `UseStaticFiles()` → `UseRouting()` → `UseAuthentication()` → `UseAuthorization()` → endpoints. Put exception handling first so it wraps everything below it.

Q33.What's the difference between HttpModule and HttpHandler (classic ASP.NET)?Advanced

Both intercept requests in classic ASP.NET. An HttpHandler is the endpoint that PROCESSES a request and produces the response for a specific resource/extension (e.g., .ashx, an image generator) — one handler ultimately serves the request. HttpModules run for EVERY request and hook pipeline events (BeginRequest, AuthenticateRequest, EndRequest) for cross-cutting concerns like logging, auth, compression. In ASP.NET Core both are replaced by middleware.

💡 Real-life example

🔌 An HttpHandler renders a dynamic chart at /chart.ashx (it IS the response). An HttpModule logs and compresses EVERY request regardless of URL. Core unifies both into the middleware pipeline.

Q34.What's the difference between a web farm and a web garden?Intermediate

A web farm is MULTIPLE servers (machines) hosting the same app behind a load balancer — for scale-out and high availability. A web garden is MULTIPLE worker processes (w3wp.exe) on a SINGLE server (IIS application pool set to >1 process) — for using multiple cores/process isolation on one box. Both break in-process session/state, so you need an external session store (SQL/Redis) in either.

💡 Real-life example

🌐 Web farm: 5 servers behind a load balancer. Web garden: 1 server, app pool running 4 worker processes. In both, an in-memory session on one process/server won't be seen by the others — use distributed cache.

Q35.How does session state management work, and what are its modes?Intermediate

Session stores per-user data across requests, keyed by a session ID (usually a cookie). Classic ASP.NET modes: InProc (in worker-process memory — fast but lost on recycle and not shared across a farm), StateServer (a separate Windows service), SQLServer (a database — durable, farm-safe), and Custom. ASP.NET Core uses IDistributedCache (in-memory, SQL, or Redis). For web farms/gardens use a distributed store, never InProc.

💡 Real-life example

🛒 A shopping cart in InProc session vanishes when IIS recycles the app pool. Move it to Redis (distributed cache) and it survives recycles and is shared across all servers in the farm.

Q36.What's the difference between authentication and authorization?Beginner

Authentication verifies WHO you are (identity) — login with credentials, tokens, OAuth. Authorization determines WHAT you're allowed to do (permissions/roles) — can this authenticated user access this resource? Authentication always comes first; authorization builds on it. In ASP.NET Core: `UseAuthentication()` then `UseAuthorization()`, with `[Authorize(Roles="Admin")]` enforcing access.

💡 Real-life example

🔐 Authentication: you log in and the system confirms you're 'Alice'. Authorization: Alice is in the 'Viewer' role, so she can read reports but the `[Authorize(Roles="Admin")]` delete endpoint returns 403.

Q37.What is a worker process (w3wp.exe) and an application pool in IIS?Advanced

In IIS, an application pool is an isolation boundary; each pool is served by one or more worker processes (w3wp.exe) that actually run your app code. Isolation means a crash or memory leak in one app pool doesn't affect apps in other pools. Pools can recycle (restart) on schedules, memory limits or idle timeouts — which is why InProc session is fragile. A web garden = one pool with multiple worker processes.

💡 Real-life example

⚙️ Site A and Site B in separate app pools → if A's w3wp crashes, B keeps running. A scheduled recycle restarts w3wp nightly, clearing any leaked memory — and wiping any InProc session.

🔌 Web API & REST (5)

Q38.What is a RESTful API and what are its core principles?Beginner

REST (Representational State Transfer) is an architectural style for web APIs over HTTP. Principles: resources identified by URIs (/users/5), standard HTTP verbs (GET read, POST create, PUT replace, PATCH partial update, DELETE remove), statelessness (each request carries everything needed — no server session), proper status codes (200, 201, 404, 400, 401), and representations (usually JSON). It's resource-oriented, cacheable and uniform.

💡 Real-life example

🔌 `GET /api/orders/42` returns order 42 as JSON with 200. `POST /api/orders` creates one and returns 201 + Location. `DELETE /api/orders/42` removes it. Verbs + nouns + status codes = RESTful.

Q39.What's the difference between REST and SOAP?Intermediate

SOAP is a strict PROTOCOL: XML-only messages, a rigid envelope, WSDL contracts, built-in standards (WS-Security, transactions), works over multiple transports. REST is an architectural STYLE: typically JSON over HTTP, lightweight, flexible, uses HTTP verbs and status codes, easier to consume from browsers/mobile. SOAP suits enterprise/finance needing formal contracts and security; REST suits most modern web and mobile APIs.

💡 Real-life example

📋 A bank's legacy payment gateway exposes a SOAP service with a WSDL and WS-Security. A mobile app's backend exposes a REST/JSON API — lighter, faster to build, trivially consumed by JavaScript.

Q40.What does it mean for a REST API to be idempotent? Which verbs are idempotent?Advanced

An operation is idempotent if making the same request multiple times has the same effect as making it once. GET, PUT and DELETE are idempotent (PUT replaces with the same payload → same final state; DELETE twice → still deleted). POST is NOT idempotent (two POSTs create two resources). PATCH may or may not be. Idempotency matters for safe retries on network failures — clients can retry PUT/DELETE without side effects.

💡 Real-life example

🔁 Retrying `PUT /users/5 {name:"Bo"}` after a timeout is safe — user 5's name is still "Bo". Retrying `POST /orders` could create two duplicate orders — so payment APIs add an idempotency key to make POST safe.

Q41.When should you use PUT vs POST vs PATCH?Intermediate

POST — create a new resource (server assigns the ID); not idempotent. PUT — create-or-replace a resource at a known URI with the FULL representation; idempotent. PATCH — apply a PARTIAL update (only changed fields) to an existing resource. Rule: POST to a collection (/orders) to create; PUT/PATCH to an item (/orders/42) to update — PUT for full replacement, PATCH for partial.

💡 Real-life example

✏️ `POST /users` creates a user (new id). `PUT /users/5` replaces user 5 entirely. `PATCH /users/5 {email:"x@y.com"}` updates only the email. Choosing wrong (e.g., POST to update) breaks REST semantics and caching.

Q42.What's the difference between Web API and an MVC controller?Intermediate

Historically ASP.NET MVC controllers returned Views (HTML) while Web API (ApiController) returned data (JSON/XML) for clients. In ASP.NET Core they unified — both derive from Controller/ControllerBase. An API controller uses [ApiController] + ControllerBase (no view support, automatic model-validation responses, attribute routing) and returns data via IActionResult/ActionResult<T>; an MVC controller adds view rendering. Same framework, different intent.

💡 Real-life example

🔀 `class HomeController : Controller` returns `View()` (HTML pages). `[ApiController] class OrdersController : ControllerBase` returns `Ok(order)` (JSON). Core merged the two pipelines into one.

🗃️ Entity Framework & Data (4)

Q43.What is Entity Framework and what are its approaches (Code First, Database First)?Intermediate

Entity Framework (EF Core) is Microsoft's ORM — it maps C# classes to database tables so you work with objects and LINQ instead of raw SQL. Approaches: Code First (write C# entities + DbContext, EF generates the schema via migrations — most popular for new apps), Database First (scaffold entities from an existing database), and the legacy Model First (design an EDMX visually). Code First with migrations is the modern default.

💡 Real-life example

🗃️ Code First: define `class Product { int Id; string Name; }` + `DbContext`, run `dotnet ef migrations add Init` and `database update` → EF creates the table. You query with LINQ: `db.Products.Where(p => p.Price > 10)`.

Q44.Explain eager, lazy and explicit loading in Entity Framework.Advanced

These control when related data is loaded. Eager loading fetches related entities up front in one query via .Include() — avoids extra round trips. Lazy loading defers loading related entities until you access the navigation property (each access fires a query) — convenient but causes the N+1 problem. Explicit loading loads related data on demand with .Entry().Collection().Load(). Prefer eager (.Include) for known needs; beware lazy loading in loops.

💡 Real-life example

🔗 Listing 100 orders and their customers: lazy loading fires 1 + 100 queries (N+1). `db.Orders.Include(o => o.Customer)` (eager) fetches everything in one JOIN — a massive performance win.

Q45.What is deferred (lazy) execution in LINQ?Intermediate

A LINQ query isn't executed when you define it — only when you ENUMERATE the results (foreach, ToList(), Count(), First()). The query is built as an expression and runs against the live data at iteration time, so changes to the source before enumeration are reflected. Operators like Where/Select/OrderBy are deferred; ToList/ToArray/Count/First force immediate execution. This enables query composition but can re-run a query if you enumerate twice.

💡 Real-life example

⏱️ `var q = list.Where(x => x > 5);` runs nothing yet. `q.ToList()` executes it. Enumerating `q` twice runs the filter twice — call `.ToList()` once to materialize and avoid re-execution.

Q46.What's the difference between ADO.NET connected and disconnected architecture?Advanced

Connected architecture keeps an open connection while reading data via a DataReader (SqlDataReader) — fast, forward-only, low memory, but holds the connection open the whole time. Disconnected architecture uses a DataAdapter to fill a DataSet/DataTable, then closes the connection; you work with the in-memory cache and reconcile changes later — better for scalability and offline edits, but uses more memory. EF Core builds on these concepts.

💡 Real-life example

🔌 Connected: a DataReader streams a million rows for a report with the connection open. Disconnected: a DataAdapter fills a DataTable, the connection closes, the UI edits rows offline, then the adapter pushes updates back.

🧩 Design Patterns (4)

Q47.What is the Singleton design pattern and how do you implement it in C#?Beginner

Singleton ensures a class has exactly one instance with a global access point. In C# the cleanest thread-safe implementation uses a static readonly field (or Lazy<T>) with a private constructor. In modern ASP.NET Core you rarely hand-roll it — you register a service with a singleton lifetime in the DI container (services.AddSingleton<IFoo, Foo>()), which manages the single instance for you.

💡 Real-life example

🧩 `services.AddSingleton<ICache, MemoryCache>();` — DI creates ONE MemoryCache for the whole app. Hand-rolled: `private static readonly Logger _instance = new Logger();` with a private ctor and a public `Instance` property.

Q48.What's the difference between a static class and a Singleton?Intermediate

Both give a single shared point of access, but: a static class can't be instantiated, can't implement interfaces or be injected, can't have instance state, and can't be mocked — it's a stateless utility holder. A Singleton is a real object (one instance) that CAN implement interfaces, be passed around, hold state, and be injected/mocked. Prefer a DI singleton over a static class when you need testability or polymorphism.

💡 Real-life example

🔧 `Math` is a static class (pure utilities, no state). A `ConfigurationService` Singleton implements `IConfigService`, holds loaded settings, and is injected — so tests can substitute a fake. Static can't do that.

Q49.What is the Factory design pattern?Intermediate

The Factory pattern delegates object creation to a separate method/class so callers depend on an abstraction, not concrete types. A Simple Factory has a method that returns instances based on input; the Factory Method pattern lets subclasses decide which class to instantiate; Abstract Factory creates families of related objects. It centralizes construction logic, decouples creation from use, and eases adding new types.

💡 Real-life example

🏭 `IShape shape = ShapeFactory.Create("circle");` — the caller doesn't `new Circle()` directly. Adding a Triangle only changes the factory, not every call site. Pairs naturally with dependency inversion.

Q50.What are the Repository and Unit of Work patterns, and how do they relate to Dependency Injection?Advanced

The Repository pattern abstracts data access behind an interface (IRepository<T> with Add/Get/Remove), so business logic doesn't depend on EF or SQL directly — improving testability and swap-ability. The Unit of Work pattern groups multiple repository operations into a single transaction and commits them together (one SaveChanges). EF Core's DbContext already IS a Unit of Work and DbSet IS a repository; you layer your own when you want stricter abstraction. Both are wired via Dependency Injection — register interfaces, inject them into services, and substitute mocks in tests (Dependency Inversion in action).

💡 Real-life example

🗃️ A service depends on `IOrderRepository` and `IUnitOfWork`, both injected. It adds an order and a payment via the repos, then `unitOfWork.SaveChangesAsync()` commits both in one transaction. In unit tests you inject in-memory fakes — no database needed.

📚 Want to go deeper?

Pair these questions with real implementation practice from our free courses: