3. Classes, Objects, and Encapsulation
Q: What is encapsulation? Encapsulation means keeping
an object’s state and invariants under the control of the object rather than allowing arbitrary external mutation.
Q: Why prefer behavior over public mutable fields?
Public mutable state allows callers to violate invariants.
Encapsulating state behind methods or controlled properties lets the class enforce valid transitions.
Q: What is the difference between a field and a
property? A field directly stores data.
A property provides an abstraction around access to data and can contain getters, setters, validation, or computed behavior.
Q: What is an auto-property? An auto-property lets the
compiler generate the backing field.
Example:
public string Name { get; set; }
Q: What is an init-only property? An
initaccessorallows a property to be assigned during object initialization but prevents normal assignment afterward.
Example:
public string Name { get; init; }
Q:
initvsreadonly?readonlyapplies to fields.
initapplies to properties and allows assignment during object initialization.
Q: What is a static member? A static member belongs to
the type rather than an individual object instance.
Design Pitfall Static state is effectively shared state.
It can complicate testing, concurrency, lifecycle management, and multi-tenant behavior.
Q: What is a sealed class? A sealed class cannot be
inherited.
It is useful when inheritance would violate the design or when the type is intentionally closed for extension.
Q: What is an abstract class? An abstract class cannot
be instantiated directly and can provide shared state or implementation for derived classes.
Q: Abstract class vs interface? An abstract class is
useful for a common base abstraction with shared implementation/state.
An interface defines a contract and allows a class to implement multiple interfaces.
Prefer interfaces for capabilities and boundaries; use abstract classes when shared implementation or state genuinely belongs in a common base.
Q: Can an interface contain implementation? Yes. Modern
C# interfaces can contain default implementations and other members, although interfaces should still primarily represent contracts.
4. Inheritance, Polymorphism, and Dispatch
Q: What is polymorphism? Polymorphism allows code to
work through an abstraction while the actual runtime type determines behavior.
Q: What is method overloading? Multiple methods have
the same name but different parameter signatures.
Overload resolution primarily happens at compile time.
Q: What is method overriding? A derived class provides
a new implementation for a virtual or abstract member defined by the base class.
Runtime dispatch chooses the appropriate override.
Q:
virtualvsoverride?virtualallows a derived class to replace a member.
overridesupplies that replacement implementation.
Q: What does
newmean when used on an inherited member? It hides the inherited member rather than overriding it.The member selected can therefore depend on the compile-time reference type.
Common Pitfall
newis not polymorphic overriding. Useoverridewhen you intend runtime polymorphism.
5. Interfaces and Generics
Q: Why use generics? Generics provide type-safe
reusable code without requiring casts and can avoid boxing for value types.
Q: What are generic constraints? Constraints restrict
the types that can be used as generic arguments.
Examples include
where T : class,struct,new(), a base class, or an interface.
Q: Why are generic constraints useful? They let the
compiler guarantee capabilities required by the generic algorithm and allow clearer APIs.
Q: What is covariance? Covariance allows a more-derived
type to be used where a less-derived type is expected for certain output-only generic abstractions.
Example:
IEnumerable<Dog>can be assigned toIEnumerable<Animal>.
Q: What is contravariance? Contravariance allows a
less-derived type to be used where a more-derived type is expected for certain input-only generic abstractions.
Example: a consumer of
Animalcan often be used where a consumer ofDogis expected.
Mnemonic Covariance = output
Contravariance = input
6. Delegates, Events, and Lambdas
Q: What is a delegate? A delegate is a type-safe
representation of a method reference.
Delegates enable callbacks, strategies, events, and functional-style APIs.
Q:
Func<>vsAction<>?Func<>represents a delegate that returns a value.
Action<>represents a delegate that returnsvoid.
Q: What is a lambda expression? A lambda is an inline
function expression, commonly used with delegates and LINQ.
Example:
x => x.Price > 100
Q: What is an event? An event provides a controlled
publisher/subscriber mechanism built on delegates.
Consumers can subscribe and unsubscribe, while the declaring type controls event invocation.
Design Pitfall Long-lived publishers retaining
subscribers can keep objects alive longer than intended. Event subscriptions can therefore contribute to memory leaks in certain object-lifecycle designs.
7. Records, Structs, and Immutability
Q: What is a record? A record is a type designed to
model data with value-oriented equality and concise immutable-style construction.
Records can be classes or structs.
Q: Record vs class? A typical class uses reference
identity unless equality is explicitly implemented.
A record is designed around value-based equality and data-centric modeling.
Q: When would you use a record for an API DTO? Records
are a good fit when the DTO represents data rather than behavior and value-based equality or immutability is desirable.
Q: What is a
record struct? It is a value-type record providing record-style value equality and concise data modeling.
Q: Struct vs class? Use a struct for small, value-like
data where value semantics are appropriate.
Use a class for entities, polymorphic objects, larger mutable state, or objects whose identity matters.
Performance Pitfall Making a large mutable struct can be
expensive because copying a value type copies its contents. Structs should generally remain small and conceptually value-like.
8. Nullable Reference Types
Q: What are nullable reference types? Nullable
reference types are a compiler analysis feature that lets developers express whether a reference is expected to be null.
Example:
stringmeans non-null intent.
string?means null is permitted.
Q: Do nullable reference types change the CLR
representation? No. They primarily provide compile-time analysis and warnings. They do not turn
stringinto a fundamentally different runtime type.
Q: What does the null-forgiving operator
!do? It tells the compiler that the developer believes an expression is non-null.It does not perform a runtime null check.
Common Pitfall
customer!.Namecan still throwNullReferenceException. The!suppresses a compiler warning; it does not make the object non-null.
Q: What does
??do? It returns the left operand if it is not null; otherwise it returns the right operand.
Q: What does
??=do? It assigns the right-hand value only when the left-hand variable is null.
Q: What does
?.do? It performs null-conditional access and returns null instead of dereferencing a null receiver.
9. Pattern Matching
Q: What is pattern matching in C#? Pattern matching
lets code test and extract information from values using patterns.
It supports type, property, relational, logical, positional, and list patterns.
Q: Why is pattern matching useful in production code?
It can make branching logic more explicit and reduce nested casts and conditionals.
Q: What are relational patterns? They allow conditions
such as
>,<,>=, and<=inside patterns.
Q: What are property patterns? They match objects based
on property values.
Example:
order is { Status: OrderStatus.Paid, Total: > 100 }
Q: What are list patterns in C# 12? List patterns allow
matching array/list-like sequences using patterns such as
[1, 2, 3]and slice patterns such as[.., 3].
10. Exceptions
Q: What is an exception? An exception represents an
abnormal condition that interrupts normal control flow and can propagate up the call stack until handled.
Q: When should you use exceptions? Use exceptions for
exceptional failures rather than ordinary expected branching.
For expected outcomes such as “customer not found” or validation failures, explicit result types or domain responses may be clearer depending on the API.
Q:
throwvsthrow ex?throw;rethrows the current exception while preserving the original stack trace.
throw ex;resets the stack-trace context at the rethrow point.
Critical Pitfall Prefer
throw;when rethrowing an exception you caught.
Q: What is exception wrapping? Exception wrapping
throws a new exception while preserving the original exception as an inner exception.
It is useful when adding domain or infrastructure context.
Q: Should you catch
Exceptioneverywhere? No.Catch exceptions where you can meaningfully handle, translate, recover, or add context. Application boundaries can catch broad exceptions for logging and consistent error responses when appropriate.
Production Pitfall Catching an exception, logging it,
and continuing silently can turn a clear failure into corrupted or inconsistent state.
11. Collections
Q:
List<T>vsHashSet<T>?List<T>preserves insertion order and provides indexed access.
HashSet<T>is optimized for uniqueness and fast membership checks.
Q:
Dictionary<TKey,TValue>vsConcurrentDictionary<TKey,TValue>?Dictionaryis not designed for concurrent mutation.
ConcurrentDictionaryprovides thread-safe operations for supported concurrent access patterns.
Q:
IEnumerable<T>vsICollection<T>vsIList<T>?IEnumerable<T>primarily represents enumeration.
ICollection<T>adds collection semantics such as count and mutation.
IList<T>adds index-based access.
Q: Why should APIs often return abstractions rather
than concrete collections? Returning an appropriate abstraction communicates what callers are allowed to rely on and reduces coupling to the concrete implementation.
12. LINQ
Q: What is LINQ? Language Integrated Query provides a
consistent query syntax and API for working with in-memory collections and other query providers.
Q: What is deferred execution? Many LINQ operators do
not execute immediately. They create a query that runs when enumerated.
Q: What is the difference between
IEnumerable<T>andIQueryable<T>in LINQ?IEnumerable<T>generally executes operations in .NET memory.
IQueryable<T>represents an expression tree that a provider, such as EF Core, can translate to another query language such as SQL.
Critical Pitfall Calling
ToList()too early can pull a large dataset into memory and move filtering from the database to the application.
Q:
SelectvsWhere?Wherefilters elements.
Selectprojects each element into another shape.
Q:
FirstvsFirstOrDefault?Firstthrows if no element exists.
FirstOrDefaultreturns the default value when no element exists.
Q:
SinglevsFirst?Singleexpects exactly one matching element and throws if there are zero or multiple matches.
Firstonly requires at least one and returns the first match.
Q: Why can multiple LINQ enumerations be dangerous? A
deferred query may execute its underlying work each time it is enumerated.
With database queries, this can result in multiple SQL executions; with expensive in-memory operations, it can repeat computation.
Performance Mnemonic Query once when appropriate → materialize once → reuse.
13. C# 12 Features
Q: What are primary constructors in C# 12? Primary
constructors allow constructor parameters to be declared directly on the type declaration.
They reduce boilerplate and can be used by classes and structs.
Q: Are primary constructor parameters automatically
fields? No.
They are parameters in scope throughout the type. The compiler creates storage only when needed by the implementation.
Common Pitfall Do not describe primary constructor
parameters as automatically becoming public properties or fields.
Q: What are collection expressions in C# 12? Collection
expressions use
[...]to create collection-like values.Examples include
[1, 2, 3]and[ ..existingItems, 4 ].
Q: What is the spread operator in C# 12 collection
expressions?
..spreads elements from another collection or compatible sequence into a collection expression.
Q: What are interceptors in C# 12? Interceptors are an
advanced compiler feature intended primarily for source generators and framework/tooling scenarios. They are not a general replacement for runtime middleware or dependency injection.
14. Async/Await
Q: What does
asyncdo?asyncenables use ofawaitwithin a method and allows the compiler to transform asynchronous control flow.It does not automatically create a new thread.
Q: What does
awaitdo?awaitasynchronously waits for a task-like operation to complete and allows the method to yield control rather than synchronously blocking the thread.
Critical Mnemonic Async does not mean "new thread."
Async primarily means don’t block while waiting.
Q:
TaskvsThread? A thread is an execution resource.A
Taskrepresents an asynchronous operation and may use thread-pool threads, I/O completion mechanisms, or other scheduling mechanisms depending on the operation.
Q: What is the thread pool? The .NET thread pool
maintains reusable worker threads for application work, reducing the cost of creating dedicated threads.
Q: What is thread-pool starvation? Thread-pool
starvation occurs when available worker threads are occupied or blocked, preventing queued work from getting threads promptly.
Synchronous blocking on asynchronous operations is a common contributor.
Production Pitfall Avoid patterns such as
.Resultor.Wait()on asynchronous operations in server code when an async path is available.
Q: Why should ASP.NET Core code generally be async all
the way down? Asynchronous I/O allows request threads to be returned to the pool while waiting for databases, HTTP services, or other I/O operations.
This improves scalability under concurrent load.
Q: What is
Task.WhenAll? It creates a task that completes when all supplied tasks complete.It is useful when independent asynchronous operations can run concurrently.
Q: When should you not use
Task.WhenAll? Do not parallelize operations that have ordering or dependency requirements, or launch unbounded numbers of tasks that can overwhelm downstream systems.
Q: What is
CancellationToken? It provides cooperative cancellation.Code observes the token and stops work when cancellation is requested.
Production Tip Cancellation is cooperative, not forcibly
aborting a thread. Propagate cancellation tokens through I/O boundaries whenever practical.
15. Memory Management and GC
Q: What is garbage collection in .NET? The GC
automatically identifies unreachable managed objects and reclaims their memory.
Q: What are GC generations? The generational GC groups
managed objects into generations based on age:
- Gen 0
- Gen 1
- Gen 2
Short-lived objects are generally collected more frequently.
Q: Why can excessive allocations hurt a high-throughput
service? Allocations increase GC work and memory pressure. Frequent allocation of short-lived objects can increase collection frequency and CPU overhead.
Q: What is
IDisposable?IDisposableprovides a deterministic cleanup pattern for resources that need explicit release, such as unmanaged handles or certain managed wrappers around external resources.
Q: Does
Dispose()free managed memory? Not directly. Garbage collection handles managed memory.
Dispose()releases resources that require deterministic cleanup.
Q: What does
usingdo?usingensuresDispose()is called when execution leaves the relevant scope, including when an exception occurs.
Q: What is
IAsyncDisposable? It provides asynchronous cleanup throughDisposeAsync(), useful when resource disposal itself requires asynchronous I/O.
Q: What is a memory leak in a garbage-collected
application? It usually means objects remain reachable even though the application no longer logically needs them.
Common causes include long-lived caches, static references, event subscriptions, and accidentally retained object graphs.
16. Thread Safety and Concurrency
Q: What is a race condition? A race condition occurs
when correctness depends on timing or interleaving between concurrent operations.
Q: What is a lock?
lockprovides mutual exclusion so only one thread at a time can enter the protected critical section for a given lock object.
Common Pitfall Do not lock on publicly accessible
objects or strings. Prefer a private dedicated lock object when using
lock.
Q: What is
Interlocked?Interlockedprovides atomic operations such as increment, exchange, and compare-and-swap for certain shared values.
Q:
lockvsInterlocked?Interlockedis useful for small atomic state transitions.
lockis appropriate when multiple operations must be protected as one critical section.
Q: What is a deadlock? A deadlock occurs when
concurrent operations wait indefinitely for resources held by each other.
Q: How can deadlocks be prevented? Establish consistent
lock ordering, minimize lock scope, avoid unnecessary nested locks, and prefer higher-level concurrency primitives where appropriate.
Q: Is
ConcurrentDictionarya replacement for every lock? No.It provides thread-safe dictionary operations, but compound business operations may still require synchronization or atomic APIs.
17. Reflection, Attributes, and Source Generation
Q: What is reflection? Reflection allows code to
inspect metadata and types at runtime and can dynamically access members.
Q: What are attributes? Attributes attach metadata to
code elements such as classes, properties, methods, and parameters.
Q: When can reflection become a performance or
architecture problem? Heavy reflection in hot paths can increase startup and runtime overhead and make code harder to analyze statically.
Modern .NET Tip Source generation can move some work from
runtime reflection to compile time, improving startup, trimming compatibility, or performance for suitable scenarios.
18. Dependency Injection and Design
Q: What is dependency injection? Dependency injection
means a class receives dependencies from an external composition mechanism rather than constructing them itself.
Q: Why is constructor injection usually preferred? It
makes dependencies explicit, supports immutability, and makes invalid object construction harder.
Q: What is the service locator anti-pattern? Service
locator hides dependencies behind a generic service lookup instead of declaring them explicitly.
This makes dependencies harder to discover and test.
Q: Interface vs abstract class in dependency injection?
Interfaces are often preferable at application boundaries because they define contracts without imposing inheritance.
Abstract classes can be appropriate when shared implementation is genuinely required.
19. Production Code Quality
Q: How do you decide whether a method should be async?
If it performs asynchronous I/O and the underlying API supports async, propagate the async model rather than blocking synchronously.
CPU-bound work is a different problem and may require different parallelism decisions.
Q: When should you use
Span<T>?Span<T>is useful for high-performance synchronous memory processing without unnecessary allocations or copying.
Q: What is
ReadOnlySpan<T>? It provides a read-only view over contiguous memory without requiring a new allocation.
Common Pitfall
Span<T>is stack-only/ref-struct-based and cannot be freely stored on the heap, captured by lambdas, or used across asynchronous suspension points.
Q: What is
Memory<T>?Memory<T>provides a memory abstraction that can be stored and used in asynchronous scenarios whereSpan<T>cannot.
20. C# Architecture Scenarios
Q: You inherit a C# service with huge methods, static
state, and direct database calls. How would you improve it? First identify behavior and dependencies before refactoring.
I would introduce boundaries around business logic, isolate persistence, remove unnecessary global state, introduce dependency injection, add characterization tests, and refactor incrementally rather than rewriting everything.
Architect Tip In production, safe incremental change beats elegant rewrites unless there is a compelling reason for a rewrite.
Q: A C# API has high CPU and high allocation rates.
What would you investigate? Profile before changing code.
Investigate allocation hot spots, serialization, LINQ materialization, string processing, boxing, excessive temporary objects, logging, JSON payload size, and algorithmic complexity.
Q: An API has low CPU but poor latency. What would you
investigate? Look for I/O waits:
- Database
- HTTP calls
- Network
- Lock contention
- Thread-pool starvation
- External service latency
- Connection-pool exhaustion
Q: An API occasionally throws
ObjectDisposedException. How would you investigate? Identify the disposed object and ownership boundary.Check service lifetimes,
usingscopes, async lifetime gaps, shared disposable instances, and whether an object is being used after its owning scope has ended.
21. C# War Stories
Q: Tell me about a C# performance problem you
diagnosed. Structure the answer:
Symptom → measurement → hypothesis → profiling evidence → fix → regression prevention.
Include concrete metrics where possible.
Q: Tell me about a concurrency bug you fixed. Explain
the shared state, race condition, observable failure, synchronization strategy, and why the fix preserved throughput.
Q: Tell me about a production memory problem in .NET.
Explain how you distinguished a true memory-retention problem from normal GC behavior, what diagnostics you used, and what object graph or allocation pattern caused the issue.
Q: Tell me about a time you rejected a clever C#
feature. Explain why readability, maintainability, debugging, performance, or team familiarity outweighed the feature’s elegance.
Senior Interview Tip Strong architects demonstrate
restraint. Knowing a language feature does not mean every codebase should use it.
22. Senior Follow-up Traps
Q: You said async improves performance. Does it always
make code faster? No.
Async primarily improves scalability for waiting-heavy workloads by avoiding blocked threads. It does not automatically reduce the intrinsic duration of the underlying operation.
Q: You said structs are faster than classes. Is that
always true? No.
Structs can avoid object allocations in some scenarios, but copying large structs can be expensive and value semantics can introduce other costs.
Q: You said
readonlymakes an object immutable. Is that true? No.
readonlyprevents reassignment of the field reference/value. If the field references a mutable object, the object’s internal state can still change.
Q: You said
IEnumerablemeans lazy. Is that always true? No.
IEnumerable<T>represents enumeration. The underlying implementation may be eager or lazy.
Q: You said
Task.Runmakes an operation asynchronous. Is that always appropriate? No.
Task.Runschedules work on the thread pool. It is generally not the solution for naturally asynchronous I/O.
Q: You said nullable reference types prevent null
exceptions. Is that true? No.
They provide compiler analysis and warnings. Runtime nulls can still occur.
Final C# Interview Mental Model For senior C# questions,
reason in this order:
Type semantics → memory → concurrency → async → performance → API design → failure mode → maintainability.