LearnThatStack Ace your next interview

C#

C# 14 on .NET 10 LTS Checked Oct 2026 117 code snippets

The model

  • Assigning a struct copies its data. Assigning a class copies only the reference, so both variables see one object.
  • Objects live on the heap. The garbage collector frees each one once nothing references it.
  • C# is statically typed. Even var gets a fixed type at compile time.
  • await frees the thread while I/O runs. Blocking on .Result wastes that thread and can deadlock.
  • LINQ queries are deferred. A query runs when you enumerate it, and again each time.
Callerawaits the Taskasync methoda state machineContext or poolruns the restI/Odisk, network, DBSTARTcall same threadawait starts the I/OTask thread is freeRESUMEdone queues the restresume after awaitresult Task completes
At the first unfinished await, the method returns a Task and frees the thread until the I/O completes.

Types & values

what a variable holds and how it copies

const, readonly and var

Fix a value at compile timeconst int Max = 100;Static, primitives and strings
Set a field once, at run timereadonly DateTime _at;
Infer a local's typevar n = 42;Typed at compile time, unlike dynamic

TrapThe compiler copies a const into every caller, so other assemblies keep the old value until rebuilt.

Classes & records

build types, inherit and override

Overload, override or hide

Reuse a name with other parametersOverloading, chosen at compile time
Replace a virtual methodoverrideChosen at run time
Hide a base methodnew void Print()
Stop further overridingsealed override

TrapWith new, a Base variable holding a Derived still runs the base method. Only override is polymorphic.

Methods & pattern matching

parameters, type tests and switch

Collections & generics

store items and write code once for many types

Delegates, events & LINQ

pass methods around and query data

Async & await

free threads while I/O runs

Threads & locks

share data safely between threads

Threads, the pool and locks

Run long, dedicated worknew Thread(Work)
Queue a job the old wayThreadPool.QueueUserWorkItemNo result or exceptions back
Let one thread inlock (_gate) { }On a private object, or a .NET 9 Lock
Increment without a lockInterlocked.Increment
Guard code that awaitsawait sem.WaitAsync();A lock body can't contain an await

TipA Task adds what a pool job lacks. You can await it, read its result, see its exceptions and cancel it.

TrapNever lock on this or a string. Code outside your class can lock the same object.

Errors & disposal

throw, catch and release resources

Throw and catch

Order catch blocksSpecific first. finally always runs
Rethrow and keep the tracethrow;
Add context, keep the causethrow new AppException(msg, ex);
Define a domain errorclass OutOfStockException : Exception

Trapthrow ex; resets the stack trace to the catch block, so the log loses the line that failed.

Memory & performance

the GC, spans and reflection

Garbage collection and leaks

Name the GC generations0 new, 1 a buffer, 2 long-lived
Force a collectionGC.Collect()Almost never
Refer to an object without keeping it aliveWeakReference<T>
Reuse a temporary bufferArrayPool<byte>.Shared

TrapEvent handlers are the classic leak. A long-lived publisher keeps every subscriber alive until it unsubscribes.

Span, stackalloc and ref structs

Slice without copyingarr.AsSpan()[2..8]
Get a small stack bufferstackalloc byte[256]
Make a stack-only typeref struct Parser
Stop a span escaping in C# 11+scoped Span<int> s

TrapA Span<T> can't be a class field or live across an await. Store a Memory<T> there instead.

ASP.NET Core & .NET

the platform, web apps, data and tests

.NET versions and project setup

Maintain a Windows-only app.NET Framework 4.8.1, fixes only
Target new worknet10.0LTS until November 2028
Trim usings and braces in C# 10+global using System.Linq;namespace App.Api;

TrapOdd-numbered releases like .NET 9 get only two years of support. An LTS release gets three.

Injection, passwords and tokens

Stop SQL injectionParameterized queries, never concatenation
Store a passwordSalted PBKDF2. Compare in constant time
Stop cross-site scriptingHttpUtility.HtmlEncode(s)

Testing and debugging

Assert in NUnitAssert.That(x, Is.EqualTo(5));
Check a mock was calledmock.Verify(m => m.Save(), Times.Once)
Test the real web appWebApplicationFactory<Program>

TipMeasure speed with BenchmarkDotNet. Stopwatch limits in unit tests make them flaky.

Found this useful? Pass it on.
Pro · $10/mo

This sheet stays free. With Pro, you can:

  • Every answer on this sheet. Read the full answer to all 112 questions it links, not just the 14 free ones.
  • My sheet. The cards you star and the ones you miss in Quiz me, from every sheet, on one page to quiz and print.
  • PDFs. Download this sheet and My sheet, laid out for A4, with every question a link to its answer.
  • The rest of Pro. Every answer in the question library, and 1,000 AI credits a month.