C# Interview Questions
Use the filter to quickly find topics like OOP, generics, collections, value vs. reference types, LINQ, async/await, delegates & events, memory management/GC, records, and performance tips.
Showing 200 of 200
What is the Common Language Runtime (CLR)?
CLR is the execution engine for .NET. It provides services like JIT compilation, memory management (GC), type safety, exception handling, and security.Explain CTS and CLS.
CTS (Common Type System) defines how types are declared and used in .NET. CLS (Common Language Specification) is a subset of CTS that ensures cross-language interoperability. CLS-compliant code can be used by any .NET language.Value type vs reference type?
Value types (structs, enums) store data directly and are allocated typically on the stack; assignment copies the value. Reference types (classes, arrays, delegates) store references to objects on the heap; assignment copies the reference.What is boxing and unboxing?
Boxing converts a value type to object (or interface) by wrapping it on the heap. Unboxing extracts the value type from the object. Both incur performance cost; avoid unnecessary boxing.Difference between string and StringBuilder?
string is immutable; every modification creates a new string. StringBuilder is mutable and efficient for many concatenations or edits.What are delegates and events?
A delegate is a type-safe function pointer. Events expose delegates in a publisher/subscriber pattern; only the declaring type can raise the event while subscribers attach handlers.Explain async/await and Task.
Task represents an asynchronous operation. async/await provides non-blocking composition of tasks by transforming the method into a state machine. Use Task for async work; Task<TResult> returns a result.Task vs Thread?
Thread is an OS thread you manage directly. Task is a higher-level abstraction that may run on the ThreadPool and composes naturally (continuations, async/await). Prefer Task for most async work.What is the using statement and IDisposable?
IDisposable exposes Dispose() to release unmanaged resources. The using statement ensures Dispose() is called even if exceptions occur. In C# 8+, use using declarations for scope-based disposal.How does garbage collection work in .NET?
.NET GC is generational (0,1,2) and compacting. It tracks object reachability, reclaims unreachable objects, and compacts memory to reduce fragmentation. Large objects are handled in the LOH.Class vs struct?
Class is a reference type with inheritance and polymorphism; struct is a value type best for small, immutable, logically atomic data. Structs should be <= 16–24 bytes and avoid defensive copying.What are records?
Records (C# 9+) are reference types optimized for immutable data models with value-based equality. You get concise syntax, with-expressions, and deconstruction.Interface vs abstract class?
Interfaces define contracts without state; a type can implement multiple interfaces. Abstract classes can contain implementation and state but allow only single inheritance.Explain extension methods.
Static methods in a static class that appear as instance methods on the extended type (first parameter preceded by 'this'). Commonly used for LINQ and helper APIs.What is LINQ and deferred execution?
LINQ provides query operators over in-memory objects, databases, XML, etc. Many LINQ operators are deferred—they build an expression/iterator executed when enumerated.IEnumerable vs IQueryable?
IEnumerable<T> is for in-memory iteration; operations execute in .NET. IQueryable<T> builds an expression tree for remote providers (e.g., EF Core) to translate into store queries.What are generics and variance (in/out)?
Generics provide type safety and performance (no boxing). Variance allows interface/delegate type substitution: 'out' is covariant (T only produced), 'in' is contravariant (T only consumed).What are nullable reference types?
A C# 8+ feature that treats reference types as non-nullable by default and uses flow analysis to warn about potential nulls. Use T? for nullable references and the null-forgiving operator (!) sparingly.Explain pattern matching in C#.
Pattern matching provides expressive checks and deconstruction (is, switch expressions, relational, logical, and property patterns) to write concise, safe type/shape-based logic.How do you implement dependency injection in .NET?
ASP.NET Core includes a built-in DI container. Register services (AddTransient, AddScoped, AddSingleton) in Program/Startup, then consume via constructor injection.What is ASP.NET Core middleware?
Middleware are components in the HTTP pipeline that handle requests/responses. They are executed in order of registration and can short-circuit or call the next component.Explain EF Core DbContext and tracking.
DbContext manages database connections and change tracking. Tracked entities have state (Added/Modified/Deleted/Unchanged). Use AsNoTracking for read-only queries to improve performance.How do you handle exceptions effectively?
Use try/catch for exceptional cases, not control flow. Prefer specific exceptions, rethrow with 'throw;' to preserve stack, and centralize handling (e.g., ASP.NET Core exception middleware).What is reflection and when to use it?
Reflection inspects metadata and types at runtime (System.Reflection). Use for dynamic loading, attribute discovery, or tooling. Avoid in hot paths due to performance/maintenance costs.What are attributes and how are they applied?
Attributes are metadata attached to program elements. Define a class derived from Attribute and decorate types/members. Read via reflection. Common ones include [Obsolete], [Serializable], [Required].What is Span<T> and when would you use it?
Span<T> is a stack-only type that provides a safe view over contiguous memory (arrays, strings, native memory) without allocations. Use it for high-performance parsing/slicing; it can't be captured on the heap or used across async boundaries.Difference between Span<T> and Memory<T>?
Span<T> is stack-only and synchronous; Memory<T> is heap-allocatable and can cross async/iterator boundaries. Use Memory<T> when you need to store or await while retaining a view.What is a record struct and how does it differ from a record class?
record struct (C# 10) is a value type with value-based equality and with-expressions; record class is a reference type with the same semantics. Choose based on value vs reference semantics.Explain ref struct and common examples.
ref struct restricts a struct to the stack to ensure memory safety (e.g., Span<T>, Utf8JsonWriter). It cannot be boxed, captured, or stored in fields of classes.What are ref returns and ref locals?
They allow returning and storing references to variables/array elements to avoid copies. Use carefully to avoid returning references to out-of-scope data.Describe lock, Monitor, and synchronization primitives.
lock is syntax sugar over Monitor.Enter/Exit for mutual exclusion. Other primitives include SemaphoreSlim, Mutex, ManualResetEventSlim, and ReaderWriterLockSlim for different concurrency needs.When should you use concurrent collections?
Use types like ConcurrentDictionary, ConcurrentQueue, and BlockingCollection to safely share collections across threads without manual locking, especially in producer/consumer scenarios.What is an iterator method and how does yield work?
An iterator method returns IEnumerable/IEnumerator (or async IAsyncEnumerable) and uses yield return to lazily produce items via a compiler-generated state machine.Explain ValueTask and when it’s beneficial.
ValueTask reduces allocations when an async result is often available synchronously. Use sparingly; it has more complex consumption rules and shouldn't be awaited multiple times.What is ConfigureAwait(false) and when should you use it?
It tells awaits not to capture the current synchronization context. In library code, use false to avoid deadlocks and improve performance; in UI code, keep the context if you must update UI after await.How do CancellationToken and cooperative cancellation work?
APIs accept a CancellationToken passed from callers. Operations should regularly check token.IsCancellationRequested or call token.ThrowIfCancellationRequested and clean up promptly.What are top-level statements and file-scoped namespaces?
Top-level statements remove boilerplate Program/Main; file-scoped namespaces (namespace X;) save indentation. Both improve minimal samples and small apps.Difference between DateTime, DateTimeOffset, and TimeZoneInfo?
DateTime lacks time-zone context; DateTimeOffset represents an absolute point in time + offset; TimeZoneInfo provides conversion rules. Prefer DateTimeOffset for persisted timestamps.System.Text.Json vs Newtonsoft.Json?
System.Text.Json is fast, built-in, and spans-based but historically had fewer features; Newtonsoft.Json is feature-rich (e.g., polymorphic converters) but slower and external. Choose per needs; custom converters can bridge gaps.How do you avoid common HttpClient pitfalls?
Reuse HttpClient via DI or IHttpClientFactory to avoid socket exhaustion, configure timeouts/policies, and prefer typed/ named clients with resiliency (e.g., Polly).Explain minimal APIs in ASP.NET Core.
Minimal APIs let you build lightweight HTTP endpoints using top-level statements and route-mapped lambdas, ideal for microservices and prototypes.What is the Options pattern?
It binds configuration sections to POCOs injected via IOptions, IOptionsSnapshot, or IOptionsMonitor for strongly-typed settings and change notifications.How do you implement JWT authentication in ASP.NET Core?
Add authentication with AddAuthentication().AddJwtBearer(), validate issuer/audience/signing key, issue tokens on login, and protect endpoints with [Authorize].Explain EF Core migrations and seeding.
Migrations capture schema changes (Add-Migration, Update-Database). Use ModelBuilder.Seed or DbContext initialization to seed data; keep seeds idempotent.What are EF Core owned types and shadow properties?
Owned types map value objects embedded in the owner entity. Shadow properties exist in the model but not in the CLR type, useful for timestamps or foreign keys.How do you add caching in .NET?
Use IMemoryCache for in-proc caching, IDistributedCache (e.g., Redis) for multi-node, and response caching middleware for HTTP. Choose appropriate expiration/eviction policies.What is SignalR and when would you use it?
SignalR provides real-time bi-directional communication over WebSockets/long polling. Use it for live dashboards, chats, notifications, or collaborative apps.Describe Hosted Services and BackgroundService.
Hosted services run background tasks in ASP.NET Core/Worker Services. Derive from BackgroundService and implement ExecuteAsync with cancellation support.What are source generators?
Compile-time tools that analyze code and emit additional C# to avoid reflection or boilerplate (e.g., serializers, DI registrations), improving performance and DX.How do you structure unit tests and mocks in .NET?
Use xUnit/NUnit/MSTest for tests, Moq/NSubstitute for mocks, and dependency injection to isolate units. Follow AAA (Arrange-Act-Assert) and aim for fast, deterministic tests.What is pattern matching in C# and where is it used?
Pattern matching lets you test and deconstruct values directly in expressions (is-patterns, switch expressions, relational/logical patterns). It simplifies type checks, null checks, and data-shape matching, e.g., `obj is Person { Age: > 18 }` or concise `switch` expressions.Explain generic constraints and why they matter.
Constraints (`where T : class`, `struct`, `unmanaged`, `new()`, base type/interface, `notnull`) restrict type parameters so the compiler can enable features (e.g., `new T()`, pointer-like ops) and improve type safety. Use them to express required capabilities and avoid runtime errors.What are covariance and contravariance?
Covariance (out) lets you use a more derived type than originally specified (e.g., `IEnumerable<object> x = IEnumerable<string>`). Contravariance (in) allows less-derived arguments (e.g., `IComparer<string>` can be used where `IComparer<object>` is expected). They apply to interfaces/delegates marked with `out`/`in` on generic parameters.What are nullable reference types (NRTs)?
NRTs provide compile-time nullability analysis. `string?` is possibly null, `string` is non-nullable. Use annotations and the `!` suppression operator sparingly. Enable in project: `<Nullable>enable</Nullable>`. Fix warnings to reduce null-reference bugs.How do records differ from classes?
Records are reference (or value with `record struct`) types with value-based equality, built-in `with` expressions, and concise primary constructors (`record Person(string Name)`), ideal for immutable data. Classes use reference equality by default.Best practices for equality in C#?
For value semantics implement `IEquatable<T>`, override `Equals(object)` and `GetHashCode()`, and overload `==`/`!=` consistently. Prefer records for immutable models. For mutable types, be careful: equality should not change while in hash-based collections.Describe the IDisposable and IAsyncDisposable patterns.
`IDisposable.Dispose()` releases unmanaged/expensive resources; use `using`/`using var`. For async cleanup (e.g., flushing I/O), implement `IAsyncDisposable.DisposeAsync()` and use `await using`. Ensure idempotency and suppress finalization when appropriate.When are finalizers needed and what is SafeHandle?
Finalizers are last-resort cleanup for unmanaged resources but are costly and non-deterministic. Prefer `SafeHandle`/`CriticalHandle` wrappers instead of raw IntPtr; combine with `IDisposable` for predictable release.What is reflection and when to avoid it?
Reflection inspects/activates types at runtime. It’s flexible but slower and harder to trim/AOT. Prefer compile-time alternatives: generics, interfaces, source generators, or `Expression`-compiled delegates for hot paths.How do custom attributes work?
Derive from `System.Attribute`, decorate targets, and retrieve via reflection (`GetCustomAttributes`). Use attributes for metadata (validation, mapping). Keep them lightweight and avoid logic in attributes themselves.Explain LINQ deferred vs immediate execution.
Most query operators are deferred—execution occurs upon enumeration (`foreach`, `ToList`, `Count`). Immediate operators materialize results. Beware multiple enumeration; cache with `ToList()` if you iterate repeatedly or side-effects exist.What is PLINQ and when should you use it?
PLINQ (`AsParallel`) parallelizes query execution over in-memory sequences. Use for CPU-bound, associative/commutative operations on large datasets. Expect unordered results unless `AsOrdered()`; measure—overhead can outweigh benefits on small inputs.Common async/await pitfalls?
Avoid blocking waits (`.Result`, `.Wait()`), which cause deadlocks. Don’t fire-and-forget unless safe and observed. Use `ConfigureAwait(false)` in libraries. Always propagate `CancellationToken` and handle exceptions with `try/await`.When to use Task.Run?
`Task.Run` offloads CPU-bound work to the thread pool in an async flow. Do not wrap inherently I/O-bound operations (which are already async) in `Task.Run`. In ASP.NET Core, prefer async I/O; heavy CPU work may need background services.Channels vs BlockingCollection for producer–consumer?
`System.Threading.Channels` are async-first, high-performance constructs for bounded/unbounded queues with backpressure. `BlockingCollection` is easier for sync scenarios but less ideal for async; Channels integrate better with async pipelines.How do ArrayPool<T> and MemoryPool<T> help performance?
They reduce GC pressure by reusing large buffers. Rent/Return arrays or IMemoryOwner<T> blocks, ensure correct sizing and always return to the pool—even on exceptions. Combine with `Span<T>`/`Memory<T>` for slicing.What is P/Invoke and how is marshalling controlled?
P/Invoke calls native functions from managed code. Control marshalling with `DllImport` and attributes like `MarshalAs`, `StructLayout`. Prefer `SafeHandle` for resource ownership; match calling conventions and character sets.What is unsafe code and when is it justified?
Unsafe code allows pointers, `stackalloc`, and `fixed` for interop or hot-path performance. It bypasses safety; restrict its surface area, validate bounds, and prefer spans when possible.Explain .NET GC basics (generations, LOH, server/workstation).
GC is generational (0/1/2) with separate Large Object Heap (LOH) and Pinned Object Heap (POH). Workstation GC favors latency; Server GC favors throughput. Minimize allocations and long-lived object promotion to reduce pauses.How do you profile and benchmark .NET apps?
Use `dotnet-trace`, `dotnet-counters`, `PerfView`, or Visual Studio Profiler for runtime diagnostics. For microbenchmarks, use BenchmarkDotNet with proper warmup, iteration counts, and non-debug builds.Describe the ASP.NET Core middleware pipeline.
Middleware are ordered components handling requests/responses. Order matters (e.g., exception handling early, auth before authorization, static files before MVC). Each calls `next()` to pass control or short-circuits.How does dependency injection work in ASP.NET Core?
A built-in container registers services with lifetimes: Transient, Scoped (per-request), and Singleton. Constructor injection is preferred. The container disposes scoped/singleton services automatically at scope end or host shutdown.What is the Configuration and Options pattern?
Configuration binds JSON/env/secret sources to POCOs. Inject settings via `IOptions<T>`, `IOptionsSnapshot<T>` (per-request), or `IOptionsMonitor<T>` (change notifications). Enable `reloadOnChange` for dynamic reload.How does logging work in .NET applications?
Use `ILogger<T>` with structured logging (`logger.LogInformation("Processed {Count}", c)`). Providers route logs to console, files, Seq, Application Insights, etc. Configure log levels by category and enrich with scopes.EF Core vs Dapper—when to choose which?
EF Core offers LINQ, change tracking, migrations—great for productivity and complex models. Dapper is a lightweight micro-ORM for fast, hand-written SQL. For mixed needs, use both: EF for most CRUD and Dapper for hot paths; manage transactions via `DbContext.Database.BeginTransaction()` or `TransactionScope`.What are init-only setters, and when should you use them?
Init-only setters (`init`) allow setting properties during object initialization but make them immutable afterward: `public string Name { get; init; }`. Use them for immutable models that still need convenient object initializers without full constructors.What are ‘required’ members in C# and how do they help?
The `required` modifier enforces that specific properties/fields must be set by the caller during initialization: `public required string Id { get; init; }`. It prevents partially constructed objects and improves correctness for domain models.Explain primary constructors for classes/structs.
Primary constructors (C# 12) let you declare constructor parameters on the type itself: `class Point(int x, int y) { public int X = x; public int Y = y; }`. They reduce boilerplate and keep parameter-to-field mapping concise.What are file-scoped namespaces and why use them?
File-scoped namespaces (`namespace MyApp;`) replace the braced block at the top of a file, removing one indentation level. They improve readability and reduce nesting in source files.What are global using directives?
Global usings (e.g., `global using System;`) apply to the entire compilation, reducing repeated `using` statements per file. Place them in a dedicated file (e.g., `GlobalUsings.cs`) to simplify imports across a project.What are top-level statements? When are they appropriate?
Top-level statements let you write a program without explicitly declaring `Main`. They’re ideal for small apps, samples, and minimal APIs, improving brevity while the compiler generates an entry point behind the scenes.What are collection expressions in C# and how do they differ from initializers?
Collection expressions (C# 12) use `[ ... ]` to create and copy collections concisely: `int[] a = [1,2,3]; var list = [..a, 4];`. They unify creation and spread (`..`) semantics across arrays, lists, and spans.Explain tuples and deconstruction with an example.
Tuples provide lightweight grouping: `(int x, int y) p = (1,2);`. Deconstruction allows `var (x, y) = p;`. They’re great for returning multiple values without defining a separate type.What are default interface methods?
Interfaces can provide method implementations (default members). This enables evolutionary designs without breaking implementers. Use sparingly—complex logic in interfaces can hurt clarity and testability.How do you implement custom indexers and ranges?
Define an indexer: `public T this[int i] { get; set; }`. Support `Index`/`Range` by adding `this[Index]` and `this[Range]` overloads. It enables `arr[^1]` (last) and slicing `arr[1..^1]` semantics.What is `Span<T>`/`ReadOnlySpan<T>` and when is it beneficial?
`Span<T>` provides stack-only, sliceable views over contiguous memory (arrays, stackalloc). It reduces allocations and improves performance for parsing/processing. Use `ReadOnlySpan<T>` for read-only scenarios and APIs that must avoid copying.Explain `Memory<T>` and `ReadOnlyMemory<T>` compared to spans.
`Memory<T>` is heap-allocatable and can live on the managed heap, making it suitable for async methods (spans are stack-only). Convert with `.Span` when needed. Use for buffering across awaits or storing slices beyond the current stack frame.What are `ref struct` and `readonly struct`?
`ref struct` types (e.g., `Span<T>`) are stack-only and cannot be boxed or captured by lambdas. `readonly struct` prevents field mutation after construction, enabling better performance and avoiding defensive copies.When should you use `ValueTask` instead of `Task`?
Use `ValueTask` when an async method often completes synchronously to reduce allocations. If the result is usually awaited once and not combined/stored, `ValueTask` can improve throughput. Otherwise prefer `Task` for simplicity.What are async streams and how do you consume them?
Async streams (`IAsyncEnumerable<T>`) support asynchronous iteration: `await foreach (var item in GetItemsAsync()) { ... }`. Use them for streaming data sources, paged APIs, or event-driven pipelines with backpressure via `CancellationToken`.How does `CancellationToken` propagate cancellation in async code?
Pass tokens through async APIs and honor them in loops and I/O calls. Use `ThrowIfCancellationRequested` to abort work cooperatively. Link tokens (`CancellationTokenSource.CreateLinkedTokenSource`) across layers for unified cancellation.Explain source generators and typical use cases.
Source generators run at compile time, inspecting code and emitting new C# to avoid reflection and boilerplate (e.g., serialization, DI registration, mapping). They improve performance and reduce runtime dependencies.What is the difference between record class and record struct?
`record` (class) is a reference type with value-based equality and `with` support. `record struct` is a value type with similar semantics. Choose based on copy cost and semantics: small, frequently-copied data fits `record struct`.How do you make HTTP calls efficiently in .NET?
Use `HttpClientFactory` to manage sockets and DNS, avoid per-call `new HttpClient()`. Add handlers for retry/circuit-breakers (e.g., Polly), configure timeouts, and reuse clients per logical API.What is the purpose of the `CallerMemberName`, `CallerFilePath`, and `CallerLineNumber` attributes?
These attributes auto-fill call-site info into optional parameters, useful for logging, INotifyPropertyChanged, and diagnostics without hardcoding method/file names.How do you implement the INotifyPropertyChanged pattern correctly?
Define `event PropertyChangedEventHandler? PropertyChanged;` and raise it from setters via `OnPropertyChanged([CallerMemberName] string? name = null)`. Check for value changes before raising to avoid redundant updates.What are minimal APIs in ASP.NET Core and when to use them?
Minimal APIs provide lightweight HTTP endpoints with top-level statements and a small hosting model. They’re ideal for microservices, prototypes, and simple REST gateways without the full MVC stack.How do you handle configuration secrets securely in .NET?
Use user secrets in development, environment variables in containers, and managed secret stores in production (Azure Key Vault/AWS Secrets Manager). Never commit secrets to source control. Bind via Configuration and Options pattern.What is trimming and AOT, and how do they impact reflection?
Trimming removes unused code to reduce app size; AOT (e.g., Native AOT) compiles to native binaries. Reflection/Dynamic features may be trimmed; annotate with `DynamicDependency`, use source generators, or preserve descriptors to remain compatible.What are common performance tuning tips for C# applications?
Avoid unnecessary allocations, prefer spans and pools for hot paths, cache expensive results, use async I/O, minimize boxing/virtual calls in tight loops, benchmark with BenchmarkDotNet, and profile using `dotnet-trace`/VS Profiler to focus on true hotspots.What is the difference between `lock`, `SemaphoreSlim`, and `ReaderWriterLockSlim`?
`lock` (monitor) is simplest for mutual exclusion within a single process and async-unsafe. `SemaphoreSlim` supports async (`WaitAsync`) and allows limited concurrency. `ReaderWriterLockSlim` allows many concurrent readers or a single writer; it’s useful for read-heavy workloads.When should you use `ConfigureAwait(false)`?
Use it in library code or background tasks where you don’t need to resume on the original synchronization context (e.g., ASP.NET Core). It reduces context-capture overhead. Avoid it in UI frameworks when you must resume on the UI thread.How do you avoid deadlocks with async/await?
Keep the async flow all the way (don’t block with `.Result`/`.Wait()`), prefer `await` everywhere, and avoid mixing sync-over-async. If you must block, isolate the work on a background thread with `Task.Run` and be aware of potential thread pool starvation.What are Channels (`System.Threading.Channels`) and when are they useful?
Channels provide high-performance, thread-safe producer/consumer queues with backpressure. They’re ideal for pipelines, background workers, and streaming data processing without manual locking.Contrast `Task.Run` vs thread pool usage directly.
`Task.Run` schedules work on the thread pool and is fine for CPU-bound tasks. Don’t use it to wrap I/O-bound operations that already provide async APIs; prefer true async I/O to free threads for other requests.Explain value-based equality in records.
Records implement value-based equality by comparing contained fields/properties, making them great for immutable domain models. Classes compare by reference by default; records reduce boilerplate for DTOs and domain events.What are list patterns and slice patterns in pattern matching?
List patterns (C# 11) match sequences, e.g., `[1, .. var rest]`. Slice `..` captures remaining elements. They enable expressive matching against arrays/spans for parsing, routers, or protocol handlers.Common LINQ performance pitfalls and remedies?
Avoid multiple enumerations; cache with `.ToList()`. Beware of `Select` + `Where` chains on hot paths; combine or switch to loops. For EF, keep queries server-side; don’t bring data to memory prematurely.EF Core: tracking vs no-tracking queries?
Tracking (`AsTracking`) keeps change-tracking overhead and is needed for updates. No-tracking (`AsNoTracking`) is faster and uses less memory for read-only scenarios, APIs, and reporting.How do you handle transactions in EF Core?
Use `await using var tx = await context.Database.BeginTransactionAsync();` then save changes and `CommitAsync()`. Alternatively use ambient transactions (`TransactionScope`) or let a single `SaveChanges()` be atomic when possible.EF Core vs Dapper—when to choose which?
EF Core offers LINQ, tracking, and rich mapping for productivity. Dapper is a micro-ORM for fast, hand-tuned SQL with minimal overhead. Choose EF for complex domains; Dapper for hot paths and read-heavy endpoints.How do you add caching effectively in .NET?
Use `IMemoryCache` for per-instance caching and `IDistributedCache` (e.g., Redis) for multi-node. Cache idempotent, read-heavy results with timeouts/size limits, and use cache keys that encode parameters and versions.Describe the Options pattern for configuration.
`IOptions<T>`, `IOptionsSnapshot<T>`, and `IOptionsMonitor<T>` bind strongly typed settings from configuration providers. Snapshot updates per request (scoped), Monitor supports change notifications, basic `IOptions` is singleton.DI lifetimes: Singleton vs Scoped vs Transient?
Singleton lives for app lifetime; Scoped lives per request in web apps; Transient creates a new instance each resolve. Avoid capturing scoped services in singletons; prefer constructor injection to keep lifetimes clear.Why does middleware order matter in ASP.NET Core?
The pipeline is sequential. Placing authentication/authorization/logging/compression in the wrong order can break features or miss instrumentation. For example, exception handling must wrap later middleware to catch errors.gRPC vs REST in .NET—trade-offs?
gRPC (HTTP/2, Protobuf) is efficient for internal microservices, streaming, and strongly typed contracts. REST/JSON is web-friendly, cacheable, and broadly interoperable. Choose based on clients, performance needs, and network constraints.When would you use SignalR?
SignalR provides real-time communication (WebSockets fallback) for notifications, dashboards, chat, and collaborative UIs. It abstracts transport details and scales via backplanes like Redis or Azure SignalR Service.How do you implement JWT authentication securely?
Validate issuer, audience, and signature; set short expirations and refresh tokens; rotate signing keys; use HTTPS only; store tokens securely (no localStorage for sensitive apps); and scope claims minimally.System.Text.Json vs Newtonsoft.Json—key differences?
System.Text.Json is built-in, fast, and AOT-friendly; supports source-gen and `JsonSerializerOptions`. Newtonsoft is more feature-rich (e.g., advanced polymorphism), but slower and heavier. Prefer STJ unless you need niche features.What are nullable reference types and why enable them?
NRTs (`#nullable enable`) treat reference nulls as part of the type system, warning about potential null dereferences. They improve correctness by forcing explicit nullability annotations and checks.What are Roslyn analyzers and how do they help?
Analyzers run at compile time to enforce style, performance, and correctness rules. Use built-in .NET analyzers, CA rules, or add packages (StyleCop, Sonar) to catch issues early and standardize code quality.How do you publish and version a NuGet package?
Author a `.csproj` with metadata (`PackageId`, `Version`, `Authors`), pack with `dotnet pack`, and push using `dotnet nuget push`. Use SemVer, include README/license, sign the package if required, and automate via CI.What is Native AOT and when to consider it?
Native AOT compiles apps ahead of time to native binaries with fast startup and low memory. It’s great for CLI tools, functions, and microservices, but limits dynamic features (reflection) and requires trim-safe code.How would you set up end-to-end observability in .NET?
Use structured logging (Serilog), distributed tracing (OpenTelemetry + exporter), and metrics (Prometheus/OpenTelemetry). Propagate trace context across services and add logging scopes for correlation.Explain the CQRS + MediatR pattern in .NET.
CQRS splits reads and writes; MediatR centralizes request/response handling. Commands mutate state, queries read state; behaviors add cross-cutting concerns (validation, logging) without scattering logic.What are `global using` directives and why use them?
`global using` (C# 10) lets you declare a using once (e.g., in a project’s Globals.cs) and have it available to all files. It reduces boilerplate and keeps files focused on domain code.Explain `file-scoped` namespaces.
File-scoped namespaces (C# 10) use `namespace MyApp;` at the top of a file to apply the namespace to all types in the file, removing one level of indentation and improving readability.When would you choose a `struct` over a `class` in C#?
Use `struct` for small, immutable value types that benefit from stack allocation and value semantics (e.g., coordinates, money). Avoid large/boxed structs because copying can hurt performance.What is a `ref struct` and a common use case?
`ref struct` must live on the stack and can’t be boxed or captured by lambdas/async. `Span<T>` is a `ref struct` enabling safe slicing of memory for high-performance parsing and I/O.Compare `Span<T>` and `Memory<T>`.
`Span<T>` is stack-only for synchronous operations; `Memory<T>` is heap-based and can cross async boundaries. Use Span for hot loops; use Memory for APIs that must be async-friendly.What are `required` members and primary constructors?
`required` (C# 11) forces initialization of properties before object construction completes. Primary constructors (C# 12 for classes/structs) let you declare constructor parameters on the type line, reducing boilerplate.Explain `record struct` vs `record class`.
`record class` is a reference type with value-based equality; `record struct` is a value type with value-based equality. Choose based on whether you need reference or value semantics.What are collection expressions in C# 12?
Collection expressions (`var xs = [1,2,3];`) provide a concise syntax for creating arrays and other collections, and support spread (`..`) to include ranges/other collections.Describe generic math and `static abstract` members in interfaces.
C# 11 allows `static abstract` members in interfaces enabling generic numeric algorithms (e.g., `INumber<T>`). It lets you write math code once for many numeric types with performance close to hand-written code.How do you stream data with `IAsyncEnumerable<T>`?
Return `IAsyncEnumerable<T>` and use `await foreach` to consume. It pulls items on demand, reducing memory and improving latency for paged queries, file lines, or HTTP streams.When should you use `HttpClientFactory`?
Always prefer it in ASP.NET Core to avoid socket exhaustion and centralize policies (timeouts, retries, auth). It manages handler lifetimes and integrates with Polly for resilience.What is the Rate Limiting middleware and a use case?
ASP.NET Core’s rate limiting middleware caps request throughput per client/key with fixed, sliding, or token buckets—use it to protect APIs from abuse and keep latency predictable.Explain `BackgroundService` and a typical pattern.
`BackgroundService` hosts long-running tasks in ASP.NET Core. Inject dependencies, loop with cooperative cancellation, and use `Channel<T>`/`Queue` to process background work reliably.How do you create Minimal APIs and why might you?
Map endpoints in `Program.cs` with `app.MapGet(...)`. Minimal APIs reduce ceremony for small services, prototypes, and serverless—still supporting DI, filters, and OpenAPI.What are source generators and why are they useful?
Source generators run at compile time to produce C# code (e.g., serializers, DI wiring) eliminating reflection and improving startup/perf. They’re great for AOT-safe libraries.How do you make code trim/AOT friendly?
Avoid reflection over unknown types; use `DynamicallyAccessedMembers` attributes, source-gen serializers, and avoid dynamic proxies. Test with PublishTrimmed/NativeAOT to catch issues.What are `Keyed` services in ASP.NET Core DI?
Keyed services (newer DI feature) allow multiple registrations of the same service type differentiated by a key, enabling strategies like multi-tenant or algorithm selection.Explain authorization policies and handlers.
Policies encapsulate requirements (claims/roles/custom assertions). Handlers evaluate requirements against the user’s `ClaimsPrincipal`. This decouples business rules from controllers.What are EF Core compiled queries?
Compiled queries cache query plans for repeated execution, avoiding expression tree compilation overhead. Use `EF.CompileQuery` for high-traffic hot paths with identical shapes.When to use EF Core value converters and owned types?
Value converters map custom types to scalar columns (e.g., `Money`, `StrongId`). Owned types model value objects embedded in the owner’s table—great for DDD aggregates.Describe Channels vs ConcurrentQueue for background work.
Channels offer async reads/writes, backpressure, and bounded capacity; ConcurrentQueue is lock-free but lacks built-in backpressure or completion. Channels fit pipelines/streaming.How do you profile and benchmark C# code?
Use BenchmarkDotNet for microbenchmarks, `dotnet-trace`/`dotnet-counters` for runtime metrics, and profilers (PerfView, VS Profiler). Measure before/after and watch GC/allocations.What is the ASP.NET Core Output Caching middleware?
It caches full responses based on policies (vary by query, headers, auth) to reduce CPU/DB load. It’s simpler than Response Caching and works with dynamic content more flexibly.How do you handle JSON polymorphism with System.Text.Json?
Use `JsonPolymorphic`/`JsonDerivedType` attributes (or source-gen) to map a base type to derived types via a discriminator. Avoid insecure ‘type name’ converters in untrusted input.P/Invoke best practices in modern .NET?
Prefer generated interop (`LibraryImport` source generator) over `DllImport`, pin and use `Span<T>`/`Memory<T>` where possible, carefully define layouts, and validate platform/bitness.What is Blazor and how do Blazor Server and Blazor WebAssembly differ?
Blazor is a .NET UI framework for web apps using C#. Blazor Server runs UI on the server over SignalR (thin client, fast startup, needs persistent connection). Blazor WebAssembly runs .NET in the browser (offline capable, larger download, no server round-trip for UI).When would you choose gRPC over REST in .NET?
Choose gRPC for low-latency, strongly-typed, contract-first RPCs, streaming (bi-directional), and inter-service communication. REST is better for broad compatibility, human-readable payloads, and public APIs.Explain server streaming and client streaming in gRPC with C#.
Server streaming returns `IAsyncEnumerable<T>` to the client; client streaming sends a stream of requests to the server; bi-directional streaming allows both. In C#, use async iterators and `await foreach` to process streams efficiently.Compare EF Core and Dapper.
EF Core is a full ORM with change tracking, LINQ, and migrations—great for productivity and complex models. Dapper is a micro-ORM focused on raw performance and manual SQL—ideal for hot paths and read-heavy endpoints.What causes N+1 query problems in EF Core and how do you avoid them?
Lazy loading or repeated navigations per item trigger many small queries. Avoid with `Include`, `ThenInclude`, projection (`Select` into DTOs), or compiled queries; consider batching or split queries where appropriate.How do you implement caching in ASP.NET Core?
Use `IMemoryCache` for in-process caching, `IDistributedCache` (e.g., Redis) for multi-instance, and Output Caching middleware for response caching. Choose appropriate expiration (absolute/sliding) and keys; cache only deterministic results.What is Polly and how would you use it with HttpClientFactory?
Polly provides resilience policies like retry with jitter, circuit breaker, timeout, and fallback. Register policies in `AddHttpClient` to automatically apply them to outbound HTTP calls for stability under transient failures.Explain idempotency in APIs and a .NET approach to implement it.
Idempotency ensures the same request can be safely retried. Use an idempotency key header and store request/response state (e.g., in Redis). On duplicate keys, return the original response instead of re-processing.What is the Outbox pattern and why use it?
Outbox ensures consistency between DB writes and message publishing. Write the message to an 'outbox' table in the same transaction as domain changes; a background worker later publishes and marks the message as sent.Describe the Saga pattern in a microservices context.
Saga coordinates a long-running transaction via a series of local transactions with compensating actions on failure. In .NET you can orchestrate via a workflow (orchestration) or via events (choreography).What’s the difference between `IDisposable` and `IAsyncDisposable`?
`IDisposable.Dispose` releases resources synchronously; `IAsyncDisposable.DisposeAsync` allows asynchronous cleanup (e.g., flush/close network streams). Use `await using` for proper async disposal.How can event handlers cause memory leaks in C#?
If a long-lived publisher holds references to subscribers via event delegates, subscribers won’t be GC’d. Unsubscribe explicitly, use weak event patterns, or confine publisher lifetime.Explain `ConfigureAwait(false)` and when to use it.
It avoids capturing the current synchronization context, reducing deadlocks and overhead in library code or server apps. In ASP.NET Core there’s no classic context, but using it in library code remains a good habit.How do you avoid ThreadPool starvation in high-throughput apps?
Use async end-to-end, avoid blocking calls (`.Result`, `.Wait()`), prefer `Task.Run` sparingly, and offload CPU-heavy work to dedicated pools. Monitor with `dotnet-counters` and adjust min threads if necessary.What are Minimal API endpoint filters and a practical use?
Endpoint filters run before/after handlers to implement cross-cutting concerns (validation, auth checks, logging). They reduce boilerplate and keep handlers clean.How do you implement validation in ASP.NET Core?
Use data annotations for simple cases, FluentValidation for richer rules, and endpoint filters or action filters to centralize validation. Return standardized `ProblemDetails` on validation errors.What is OpenTelemetry and how do you use it in .NET?
OpenTelemetry standardizes tracing/metrics/logs. In .NET, add `AddOpenTelemetry()`, instrument ASP.NET Core/HttpClient/EF Core, and export to Jaeger, OTLP, or Azure Monitor for distributed tracing and performance insights.How would you structure logging for production diagnostics?
Use structured logging with message templates (Serilog, Microsoft.Extensions.Logging), enrich with correlation IDs, log levels and scopes, and ship to centralized sinks (Seq, ELK, Azure, Splunk).JWT vs Cookie authentication in ASP.NET Core—when to choose which?
JWT is stateless and ideal for SPA/mobile APIs and gateways; cookies are stateful (or server-validated) and convenient for traditional web apps. Consider token size, rotation, CSRF, and SameSite for your scenario.Explain CORS and preflight in ASP.NET Core.
CORS allows cross-origin requests. Preflight (`OPTIONS`) checks methods/headers. Configure named policies with `WithOrigins`, `AllowAnyHeader/Method`, and register with `UseCors` before endpoints.What’s `IHostedService`/`BackgroundService` lifecycle and graceful shutdown?
Services start on host start and stop on shutdown. Respect `CancellationToken` in execute loops, handle `StopAsync`, and ensure cleanup/flush in `Dispose` or `IAsyncDisposable` for graceful termination.How do you handle secrets configuration in .NET?
Use User Secrets in dev, environment variables in containers, and a secret store like Azure Key Vault in production. Bind strongly typed options and avoid committing secrets to source control.Performance tips: how to reduce allocations in hot paths?
Use `Span<T>`/`Memory<T>`, `ArrayPool<T>`, `StringBuilder` for concatenation, value-type enumerators where possible, and avoid LINQ in tight loops. Benchmark with BenchmarkDotNet to validate gains.What are ReadyToRun (R2R) and PGO in .NET?
R2R precompiles IL to native to improve startup; PGO (Profile-Guided Optimization) tunes JIT based on real workloads for better throughput. Combine for faster startup and steady-state performance.How do you test ASP.NET Core endpoints effectively?
Use `WebApplicationFactory` for in-process integration tests, swap infrastructure with test doubles or Testcontainers, seed data, and assert status codes/headers/body. For HTTP clients, mock via `HttpMessageHandler`.What are C# Source Generators and when would you use them?
Source Generators run at compile time to produce C# code based on your project’s inputs (attributes, files, metadata). They reduce reflection cost, boilerplate, and runtime overhead (e.g., JSON serializers, DI registrations, INotifyPropertyChanged).What is a Roslyn Analyzer and how does it differ from a Source Generator?
Analyzers inspect code during compilation to enforce rules and provide diagnostics/code fixes. Generators produce code. Use analyzers to guide style, API usage, and safety; use generators to emit source to compile.Records vs classes vs struct records—how do they differ?
Records default to value-based equality and concise immutability. Classes have reference equality by default. Struct records are value types with record semantics, avoiding allocations but must be kept small and immutable.What are file-scoped namespaces and global usings in C# and why use them?
File-scoped namespaces reduce indentation; global usings centralize common imports. Together they simplify files, reduce boilerplate, and improve readability—especially in minimal API projects.Explain modern pattern matching features in C# (e.g., relational, logical, and list patterns).
Relational (>, <), logical (and, or, not), and list patterns allow expressive matching without verbose code—e.g., `if (x is > 0 and < 10)`, or `if (arr is [0, .. var rest])`—making validation and parsing concise.When should you use `readonly struct` and when `ref struct`?
`readonly struct` enforces immutability and avoids defensive copies. `ref struct` (e.g., `Span<T>`) is stack-only and cannot be boxed, captured, or used in async; use it for high-performance stack-bound data.What are `Span<T>` and its safety limits?
`Span<T>` is a stack-only view over contiguous memory enabling allocation-free slicing. It can’t be used as fields in classes, can’t be boxed, and can’t cross async/iterator boundaries; use `Memory<T>` when heap or async is required.How does `Memory<T>` differ from `Span<T>`?
`Memory<T>` is a heap-friendly, awaitable-safe counterpart to `Span<T>`. You can store `Memory<T>` in fields and use it across async methods; call `.Span` to access the underlying `Span<T>` when needed.Channels vs BlockingCollection—when should you use Channels?
`System.Threading.Channels` is async-first, high-throughput, and unbounded/bounded with backpressure. Use Channels for producer/consumer pipelines with `await` in modern apps; prefer over `BlockingCollection` for async scenarios.What is `System.IO.Pipelines` and where does it shine?
Pipelines provide high-performance, zero/low-copy buffered I/O for streaming protocols (HTTP, gRPC, custom binary). They excel in scenarios with partial reads/writes and backpressure, minimizing allocations.`Task` vs `ValueTask`—when to prefer `ValueTask`?
Use `ValueTask` when a result is synchronously available much of the time to avoid Task allocation. Do not `await` a `ValueTask` multiple times or store it long-term. Prefer `Task` by default; micro-opt only in hot paths.How do you implement async streaming with `IAsyncEnumerable<T>`?
Return `IAsyncEnumerable<T>` and use `await foreach`. Support cancellation via `CancellationToken` in `GetAsyncEnumerator`. It’s ideal for paged data, server streaming (SignalR/gRPC), and backpressure-friendly APIs.Explain DI lifetimes in ASP.NET Core and thread-safety concerns.
Singleton (app-long), Scoped (per request), Transient (new each injection). Singletons must be thread-safe. Don’t capture scoped services in singletons. Prefer stateless services and immutable configuration.Minimal APIs vs MVC Controllers—trade-offs?
Minimal APIs provide lean startup and concise endpoints; great for microservices. Controllers offer filters, model binding breadth, and conventions. Choose minimal for small services; controllers for large, conventional apps.How do you perform validation in Minimal APIs?
Validate DTOs with data annotations or FluentValidation; return `Results.ValidationProblem`. Endpoint filters can centralize validation. For complex cases, map groups with filters for cross-cutting concerns.What is the .NET Rate Limiting middleware and how do you use it?
Add `AddRateLimiter` and configure fixed/windowed/concurrency/token-bucket policies. Apply globally or per-endpoint with `RequireRateLimiting`. It protects services from abuse and smooths load.How does ASP.NET Core Data Protection work?
It manages key rings to encrypt cookies and other data. Store keys persistently (file system, Redis, Azure Blob) across instances; rotate keys automatically. Never hardcode keys; back up the key store.How should passwords be stored in .NET apps?
Never store plain text. Use strong, salted hash algorithms (PBKDF2 via ASP.NET Identity, or BCrypt/Argon2). Enforce iteration counts, per-user salt, and secure password policies and rotation.What are health checks in ASP.NET Core?
Health checks expose liveness/readiness endpoints for probes. Register checks (DB, cache, external deps) and map endpoints (`/health/live`, `/health/ready`) for orchestrators like Kubernetes.How can you implement feature flags in .NET?
Use `Microsoft.FeatureManagement` or LaunchDarkly/Flagsmith. Decorate code paths with `[FeatureGate]` or check `IFeatureManager`. Store flags in config or remote providers; support gradual rollouts.How do you handle optimistic concurrency in EF Core?
Add a concurrency token (e.g., `rowversion`/`Timestamp`). On save conflicts EF throws `DbUpdateConcurrencyException`; resolve by client-wins/server-wins or manual merge and retry.What are EF Core compiled queries and benefits?
Compiled queries precompile LINQ into delegates, avoiding repeated translation. They reduce overhead in hot paths with repeated shapes. Use `EF.CompileQuery` or `FromExpression` patterns.Testing EF Core: InMemory vs SQLite in-memory?
The InMemory provider doesn’t enforce relational behaviors (constraints, transactions). SQLite in-memory is closer to real SQL semantics. Prefer SQLite in-memory for realistic integration tests.Best practices for containerizing .NET apps?
Use official slim base images, multi-stage builds, non-root user, environment-based config, health endpoints, and readiness probes. Consider trimming, R2R, and publishing for your target RID.What is Native AOT in .NET and trade-offs?
Native AOT ahead-of-time compiles to a self-contained native binary with fast startup and low memory. Trade-offs: limited reflection/dynamic code, larger build complexity, and some library restrictions.