Skip to main content

Advanced C# Interview Questions

Every question has a short model answer and a link to the lesson example that shows it in code. Levels: F = Fresher (0-2 yrs), M = Mid (3-5 yrs), S = Senior (6-9 yrs), A = Architect / Lead (10+ yrs).

Collections

FWhat is the difference between an array and a List<T>?concept

An array has a fixed size set when it is created. A List<T> grows and shrinks with Add and Remove, using an array inside that it replaces with a bigger one when full. Use arrays for fixed data and lists for data that changes.

FWhen would you use a Dictionary<TKey, TValue>?concept

When you look values up by a unique key, such as students by admission number. Lookup time stays about the same however many items it holds, unlike searching a list.

FWhat is the difference between a Queue and a Stack?concept

A Queue<T> is first in, first out: Enqueue adds at the back, Dequeue takes from the front, like a fee counter line. A Stack<T> is last in, first out: Push and Pop work on the top, like undo.

MWhy is looking up by key in a Dictionary faster than searching a List?concept

A list search checks items one by one, so on average half the list per search. A dictionary hashes the key to jump almost directly to its bucket, taking about constant time. In the SMS, finding 1,006 students took about 24 ms with a list and 0.1 ms with a dictionary.

MWhat is the difference between dict[key] and dict.TryGetValue(key, out value)?coding

The indexer throws KeyNotFoundException when the key is missing. TryGetValue returns false instead and gives the value through out when found. Use TryGetValue whenever the key may be absent.

MWhat does 'Collection was modified; enumeration operation may not execute' mean?concept

The list was changed, for example by Remove, while a foreach was looping over it. Collect the items to change and apply the changes after the loop, or loop backwards with a for loop.

SAn end-of-term report takes minutes. It loops over students and, for each, searches a list of all marks. How do you fix it?scenario

The nested search does students times marks comparisons. Group the marks into a Dictionary keyed by student once, then look each student up in constant time. The work drops from millions of comparisons to one pass plus one lookup per student.

How to answer:

Identify the nested loop as the cause, explain the complexity in plain terms, and show the dictionary fix with a measurement before and after.

SHow should a class expose a collection it owns?design

Keep the real list private and expose it as IReadOnlyList<T> or IReadOnlyCollection<T>, so callers can read but not add or remove. Changes go through the class's own methods, which keep its rules. Initialise collections to empty, never null.

How to answer:

Connect it to encapsulation, show the property pattern, and mention that returning the mutable list lets callers bypass validation.

AHow do you choose the right collection for a feature?design

Start from how the data is used: in order and by position (List), by key (Dictionary), uniqueness checks (HashSet), arrival order (Queue), last-first (Stack), and whether many threads share it (concurrent collections). Measure with realistic data volumes before optimizing further.

How to answer:

Give a decision approach based on access patterns and scale, with SMS examples, and mention thread safety and memory as further factors.

Generics

FWhat are generics in C#?concept

Classes, records, interfaces, and methods written with a type parameter, such as T, that the caller fills in. List<Student> and PagedResult<StudentDto> reuse one definition for many types, with full compile-time type checking.

FWhat is a generic method?concept

A method with its own type parameter, written after its name, such as ToPage<T>(List<T> all, int page, int pageSize). The compiler usually infers T from the arguments, so callers rarely write it.

FWhy are generic collections better than ArrayList?concept

ArrayList holds object, so wrong types are accepted and fail later with InvalidCastException, and value types are boxed. List<decimal> rejects a string at compile time and stores decimals directly, which is safer and faster.

MWhat are generic constraints? Give examples.concept

Rules on what a type parameter may be, written with where: where T : ISoftDeletable, where T : class, where T : struct, where T : new(). They let the generic code use the promised members, and the compiler rejects types that do not qualify (CS0311).

MWhat is boxing, and how do generics avoid it?concept

Boxing wraps a value type, such as a decimal, in an object on the heap so it can be stored as object; unboxing casts it back. It costs memory and time. Generic collections store the value type directly, so no boxing happens.

MWhy can't a List<Student> be assigned to a List<Person>, while IEnumerable<Person> works?concept

Through a List<Person>, code could add a Teacher into a list of students, so C# forbids it (CS0029). IEnumerable<T> only reads, so treating students as persons is safe; this is covariance, marked by out T on the interface.

SFour teams each built their own paging response for the API, and the mobile app struggles. What do you do?scenario

Define one generic PagedResult<T> in the shared library with agreed names, 1-based pages, and a maximum page size, and migrate endpoints to it gradually, keeping old shapes until clients move. Clients then need one paging routine.

How to answer:

Cover the shared contract, the rules it enforces (page size limits), and a safe migration plan with versioning or a transition period for existing clients.

SWhat are the pros and cons of a generic repository, IRepository<T>?design

Pros: less repetitive code and a uniform interface. Cons: every entity gets the same methods, including Delete where rules forbid it; special queries are awkward; and it often duplicates what an ORM already provides. Specific repositories, possibly sharing a small generic base, are a common choice.

How to answer:

Present both sides fairly, tie the decision to business rules (forbidden deletes) and query needs, and mention that EF Core's DbSet already acts as a generic repository.

AHow would you design shared generic building blocks for a large API without over-generalizing?design

Generalize proven, repeated shapes, such as paging, result wrappers, and soft-delete filters, with minimal constraints, in a shared library. Keep domain logic specific. Make something generic only when a second real use appears, and document the conventions so teams use them consistently.

How to answer:

Show judgment: name good candidates and bad ones (generic services hiding business rules), discuss constraints and naming, and the cost of changing widely used generic types.

IEnumerable and IQueryable

FWhat is IEnumerable<T>?concept

The interface for anything you can walk through one item at a time. It provides an enumerator, which foreach uses. Arrays, lists, dictionaries, and LINQ queries all implement it.

FWhat does yield return do?concept

It hands back one item from a method that returns IEnumerable<T>, then pauses the method until the caller asks for the next item. Data is streamed: reading the marks file with Take(3) read only 71 of 12,012 lines.

FWhat is deferred execution in LINQ?concept

Building a query with methods like Where does not run it; it creates a plan. The plan runs only when results are requested, by foreach, Count(), First(), ToList(), and similar calls.

MWhat is the difference between IEnumerable<T> and IQueryable<T>?concept

An IEnumerable query holds compiled code and runs in your application's memory. An IQueryable query holds an expression tree that a provider translates, for example EF Core into SQL, so filtering happens in the database before rows are sent.

MWhat is multiple enumeration, and how do you avoid it?concept

Enumerating the same deferred query more than once repeats all its work each time; two Count() calls read the marks file twice. If the results are needed several times, call ToList() once and reuse the list.

MWhy prefer Any() over Count() > 0?coding

Any() stops at the first matching item; Count() must examine every item. Against a database, Any() becomes an EXISTS check while Count() counts every matching row.

SA dashboard calls context.AttendanceRecords.ToList() and then filters today's records in C#. It is slow and uses a lot of memory. Why, and what is the fix?scenario

ToList() runs the query immediately, so every attendance row is loaded into memory before filtering. Apply Where while the query is still IQueryable, then ToList(), so SQL Server returns only today's rows.

How to answer:

Explain where the query runs before and after the fix, quantify the waste (all rows versus a few hundred), and mention checking the generated SQL or logs to confirm.

SShould a repository return IQueryable<T>?design

Usually not. Returning IQueryable lets callers compose any query against the database, spreading data access logic and making performance unpredictable. Return materialized results such as IReadOnlyList<T>, and add specific methods for the queries you need.

How to answer:

Present the trade-off: flexibility versus control and testability. Mention cases where exposing IQueryable is deliberate, such as OData or internal query builders.

AHow would you process millions of rows in .NET without running out of memory?design

Stream instead of materializing: read rows one at a time with an iterator, a data reader, or IAsyncEnumerable<T>, process each, and keep only aggregates. Filter and aggregate in the database where possible, and batch writes.

How to answer:

Combine database-side work, streaming in the application, batching, and measuring memory. Mention that ToList on huge results is the usual cause of memory spikes.

LINQ

FWhat is LINQ?concept

Language Integrated Query: a set of C# methods and syntax for querying any collection, such as Where, Select, OrderBy, and GroupBy. The same queries work on lists, files, and, through EF Core, databases.

FWhat is the difference between Where and Select?concept

Where filters: it keeps items that match a condition. Select projects: it turns each item into a new shape, such as a name and a mark. Filter first, then shape.

FWhat is the difference between First, FirstOrDefault, and Single?concept

First returns the first match and throws if there is none. FirstOrDefault returns default (null for classes) instead of throwing. Single expects exactly one match and throws for none or for more than one.

MHow does LINQ's Average treat null values?concept

For nullable values, Average, Max, and Min skip nulls, like SQL's AVG. The Class 10 Mathematics average of 60.23 ignored 20 absent students, matching SQL Server exactly.

MHow does GroupBy work in LINQ?coding

GroupBy(m => m.Subject) returns groups; each has a Key (the subject) and is itself the sequence of items with that key, so g.Average(...) and g.Count() work per group, like SQL's GROUP BY.

MWhat is the difference between Select and SelectMany?concept

Select returns one result per item, so a list of sections with enrollments becomes a list of lists. SelectMany flattens those inner lists into one sequence: 22 sections become 1,006 enrollments.

SA results screen shows a different rank-1 student on every refresh. What is wrong?scenario

Several students share the top mark and the sort has no tie-breaker, so their order is not fixed. Add ThenBy on a stable key, and agree a ranking rule with the school, such as equal marks sharing a rank (DENSE_RANK).

How to answer:

Explain non-deterministic ordering, the technical fix, and the business question behind it. Mention the same issue in SQL ORDER BY without a unique key.

SQuery syntax or method syntax: which do you use?concept

Both compile to the same calls. Method syntax is shorter for simple chains and offers every operator; query syntax reads more easily for joins and multiple sources. Many teams default to method syntax and use query syntax for complex joins.

How to answer:

Show you can read and write both, then state a consistent team preference and its reason.

AWhen does LINQ hurt performance, and how do you prevent it in a team?design

Through searches inside loops instead of dictionaries, repeated enumeration of deferred queries, materializing database queries too early, and sorting before filtering. Prevent it with code review rules, analyzers for multiple enumeration, logging of generated SQL, and measuring hot paths.

How to answer:

Give concrete anti-patterns with fixes, then the team-level practices. Emphasize measuring before replacing readable LINQ with hand-written loops.

Delegates and events

FWhat is a delegate?concept

A type-safe reference to a method, stored in a variable and passed around like a value. Func, Action, and EventHandler<T> are built-in delegate types; LINQ's Where takes a delegate.

FWhat is the difference between Func and Action?concept

Func returns a value; its last type parameter is the return type, as in Func<decimal, string>. Action returns nothing, as in Action<string>.

FWhat is a lambda expression?concept

An inline, unnamed method, such as m => m.MarksObtained is null. It is converted into a delegate (or an expression tree for IQueryable), with parameter types inferred from where it is used.

MWhat is an event, and how does it differ from a public delegate field?concept

An event is a delegate wrapped so that outside code can only subscribe (+=) and unsubscribe (-=); only the owning class can raise it. A public delegate field could be overwritten or invoked by anyone, faking notifications (CS0079 prevents this for events).

MWhat is a closure?concept

A lambda that captures variables from its surrounding scope. It captures the variable itself, not a copy, so changes are shared and the captured objects stay alive as long as the lambda does.

MWhy raise an event with Event?.Invoke(...), and why can't you unsubscribe an inline lambda?coding

With no subscribers the event is null, so ?. avoids a NullReferenceException. Each inline lambda creates a new delegate, so -= with another identical-looking lambda removes nothing; keep a reference or use a named method.

SRecording a payment calls six features directly, and a bug in any one breaks payments. How would you redesign it?scenario

Have the payment raise one "payment recorded" event, or publish a message, after the payment is saved, and let each feature subscribe independently. Failures in optional reactions should not undo or block the payment; isolate them and log errors.

How to answer:

Connect to Single Responsibility and Open/Closed, discuss error isolation, and mention that across services this becomes messaging with background processing.

SWhen would you use an event, an interface, or a Func parameter?design

An event for optional listeners that come and go; an interface for a required collaborator with several methods, injected through the constructor; a Func parameter for a single rule or formula chosen by the caller.

How to answer:

Give one SMS example for each and the trade-offs: discoverability, testability, and how failures propagate.

AHow do in-process events relate to messaging in a distributed system?design

Both announce that something happened and let others react. In-process events run synchronously in the same program and are lost if it crashes. Messaging (queues, an outbox) is durable, crosses services, retries on failure, and runs asynchronously, at the cost of eventual consistency.

How to answer:

Compare reliability, coupling, and timing, then explain when to promote an event to a message, for example a payment notification that must not be lost.

Modern C# features

FWhat is a collection expression?concept

C# 12 syntax for creating collections with square brackets: string[] subjects = ["English", "Science"];. It works for arrays, lists, and other collection types, and .. spreads another collection's items in.

FWhat is a raw string literal, and when is it useful?concept

Text between three double quotes ("""), where quotes and backslashes need no escaping and the closing quotes' indentation is removed. It suits SQL, JSON, and other text with quotes; values still belong in SQL parameters.

FWhat does the C# 14 field keyword do?concept

Inside a property accessor, field refers to the property's compiler-made backing field, so a property with a custom setter, such as trimming or validation, no longer needs a hand-written private field.

MWhat are list patterns?concept

Patterns that match the shape of a sequence: ["Absent", ..] (first item is Absent), [.., "Absent", "Absent"] (last two), [_, _, _] (exactly three items). _ matches one item and .. any number of items.

MHow do primary constructors on classes differ from records?concept

Both declare parameters after the type name. A record turns them into public init-only properties with value equality. A class with a primary constructor only makes the parameters available inside the class body; they are not properties, and they are not read-only.

MWhat are C# 14 extension members?concept

An extension(Type receiver) { ... } block inside a static class that can declare extension properties as well as methods, such as student.Initials. Before C# 14, only extension methods were possible.

SA developer converted half the codebase to new C# syntax in one pull request. How do you handle it?scenario

Ask to split it: a large mechanical change hides real changes and is hard to review. Agree on which features the team adopts, apply them in new and changed code, and convert old code gradually or with automated, separately reviewed refactorings.

How to answer:

Balance modernization against reviewability and risk. Mention coding standards, analyzers or editorconfig rules, and keeping behavior changes separate from style changes.

SShould a switch over an enum end with a default arm? What are the trade-offs?design

Without _, the compiler warns about missing statuses (CS8509) and unnamed values (CS8524), which helps when new statuses are added. A quiet default hides new statuses. A common choice is to list every status and end with _ => throw, so unexpected values fail loudly.

How to answer:

Explain both warnings, the risk of silent defaults, and the throwing default as a middle path.

AHow would you keep a large codebase current with new .NET and C# versions?design

Upgrade to each LTS release on a plan, update the target framework and packages, fix analyzer warnings, and adopt new language features through agreed coding standards in new and changed code. Automated tests make upgrades safe, and editorconfig or analyzers keep the style consistent.

How to answer:

Cover the upgrade cadence (LTS), risk control (tests, staged rollout), and team practices for adopting features. Mention support end dates as the business driver.

async and await

FWhat do async and await do?concept

async marks a method that can use await and returns Task or Task<T>. await pauses the method until a task completes, giving the thread back in the meantime, and continues from the same line afterwards.

FWhat is the difference between Task and Task<T>?concept

Both represent work that finishes later. Task has no result, like writing a log file; Task<T> produces a value of type T, like Task<string> for a send status.

FDoes async make code run faster?concept

Not by itself. It makes waiting for I/O cheaper by freeing threads, which improves scalability and lets independent waits overlap. CPU-bound calculations need parallelism instead.

MHow do you run several independent async operations together?coding

Start them without awaiting, collect the tasks, and await Task.WhenAll(tasks). Ten 250 ms sends took about 260 ms together instead of 2.6 seconds one by one. Results come back in the same order.

MWhat is a CancellationToken, and why pass it through async methods?concept

A token that signals that work should stop, created by a CancellationTokenSource, for example with a time limit. Passing it down to every async call lets the whole operation stop early; ASP.NET Core cancels it when the client disconnects.

MWhy should you avoid async void?concept

An async void method cannot be awaited, so callers cannot know when it ends, and exceptions it throws cannot be caught by the caller and can crash the process. Return Task instead; use async void only for event handlers.

SA web portal stops responding under load, but the CPU is nearly idle. The code uses .Result on database calls. What is happening?scenario

Thread pool starvation: each request blocks a thread while waiting for the database, so the pool runs out and new requests queue. Make the call chain async all the way with await, so threads are released during waits.

How to answer:

Explain the symptom (low CPU, high latency), the cause (blocked threads), the fix, and how to confirm it with thread pool counters or dotnet-counters.

SHow are exceptions handled with Task.WhenAll?concept

WhenAll waits for all tasks to finish, then await rethrows the first exception; the other tasks still complete. Inspect each task's status or the aggregate Exception to see all failures, and design batches so one failure does not stop the rest.

How to answer:

Show awareness that only the first exception surfaces through await, and how to collect all errors for reporting in batch jobs.

AHow would you send fee reminders to 10,000 families reliably and quickly?design

Send asynchronously with limited concurrency (for example batches or a semaphore) so the provider is not overwhelmed, with timeouts and cancellation, retries for temporary failures, and a record of what was sent so a restart does not send twice. Run it as a background job, not inside a web request.

How to answer:

Cover throughput (bounded concurrency), reliability (retries, idempotency, persistence), provider limits, and observability. Mention background workers in Module 12.

Threading

FWhat is the difference between a thread and a task?concept

A thread is a path of execution managed by the operating system. A task is a unit of work that .NET schedules, usually on a reusable thread-pool thread. Modern code uses tasks, Parallel, and async instead of creating threads by hand.

FWhat is a race condition?concept

A bug where the result depends on the timing of threads that share data. Two threads doing count++ can both read the same value and write the same result, losing an update; one million increments gave about 62,000.

FWhat does Parallel.ForEach do?concept

It processes the items of a collection on several thread-pool threads at once, using multiple cores. It suits CPU-bound, independent work, such as building 1,006 report cards about three times faster on 16 cores.

MWhen would you use Interlocked instead of lock?concept

Interlocked performs a single update on one number, such as increment or add for int and long, as one uninterruptible step, without blocking. Use lock when several fields change together, for types like decimal, or for collections.

MWhy might parallel code be much less than N times faster on N cores?concept

Splitting and combining work costs time, cores share memory bandwidth, locks make threads wait, and parts of the program run on one thread only (Amdahl's law). Very small work items can even be slower in parallel.

MIs Dictionary thread-safe? What do you use instead?concept

No: adding from several threads at once can lose items or corrupt it. Use ConcurrentDictionary (or other System.Collections.Concurrent types), or let each thread build its own results and combine them afterwards.

SA parallel term-end report gives a slightly different fee total each run. What is wrong, and how do you fix it?scenario

Threads add to one shared total without protection, so updates are lost in a race. Fix it by computing independent partial totals per section or thread and adding them at the end, or by protecting the shared total with a lock. Then test repeatedly with production-sized data.

How to answer:

Recognise the symptom of nondeterminism, name the race, give the share-nothing fix first and the lock as an alternative, and mention why such bugs pass normal tests.

SWhat is a deadlock with locks, and how do you avoid one?concept

Two threads each hold one lock and wait for the lock the other holds, so both wait forever. Avoid it by taking locks in a fixed order, keeping locked sections small, avoiding nested locks, and never awaiting or calling unknown code while holding a lock.

How to answer:

Explain the circular wait, prevention rules, and diagnosis with a debugger or dump showing thread stacks. Relate it to the SQL deadlocks of Lesson 25.

AHow do you design a web application so that concurrent requests do not corrupt shared state?design

Keep request handling stateless: per-request objects, no mutable static fields, data in the database with transactions and constraints. Where in-memory sharing is needed, such as caches, use thread-safe types and immutable data, and keep heavy CPU work in background jobs.

How to answer:

Cover the request model (many threads), where state should live, synchronization choices, and service lifetimes in dependency injection (singleton services must be thread-safe).

Memory and GC

FWhat is the difference between the stack and the heap?concept

The stack holds method-local value-type variables and references, freed automatically when a method returns. The heap holds objects such as class instances, arrays, and strings, freed by the garbage collector when nothing references them.

FWhat does the garbage collector do?concept

It periodically finds objects that running code can no longer reach and reclaims their memory, then compacts the surviving objects. Developers do not free managed memory by hand.

FWhat is IDisposable, and what does using do?concept

IDisposable has one method, Dispose, which releases resources the GC does not manage, such as files and connections. using calls Dispose automatically at the end of a block, even if an exception is thrown.

MWhat are GC generations?concept

Generation 0 holds new objects and is collected often; survivors move to generation 1, then to generation 2, which is collected rarely. Most objects die young, so this makes collection cheap. Objects of 85,000 bytes or more start on the large object heap, counted as generation 2.

MWhat is the difference between Dispose and a finalizer?concept

Dispose releases resources at a known moment, called by your code or using. A finalizer runs when the GC collects the object, at an unknown time, on a special thread, and delays collection. Prefer Dispose; modern code rarely writes finalizers because SafeHandle covers them.

MHow can events cause memory leaks?concept

An event holds delegates, and each delegate references its subscriber. If a long-lived object's event keeps a short-lived subscriber, the subscriber cannot be collected until it unsubscribes. Unsubscribe with -=, often in the subscriber's Dispose.

SAn API's memory grows every day until it needs a restart. How do you investigate?scenario

Watch memory and GC counters over time, take memory snapshots at two points, and compare which object types grow and what keeps them alive. Typical culprits are event subscriptions on long-lived services, static collections, unbounded caches, and undisposed resources.

How to answer:

Describe a measured approach (dotnet-counters, dumps or Visual Studio snapshots, retention paths), the common causes, and verifying the fix under load.

SShould you call GC.Collect() in application code?concept

Almost never. The GC tunes its own timing, and forcing collections usually costs performance by promoting objects and pausing the program. It is useful in experiments and tests that measure memory, as in this lesson.

How to answer:

Explain the cost, the rare legitimate cases, and what to do instead: fix the cause of memory growth.

AHow do you design a high-traffic .NET service to be memory-efficient?design

Stream large data instead of loading it, avoid many short-lived large objects, reuse buffers (pooling), bound every cache, dispose resources promptly, avoid long-lived references to per-request objects, and monitor GC metrics in production.

How to answer:

Cover allocation patterns, lifetimes, pooling, caching limits, and observability, with an example such as exporting attendance for a whole school.