Records and Primary Constructors
Records provide value semantics, built‑in equality, and with‑expressions for succinct immutable models. They reduce boilerplate in DTOs, events, and domain value objects. Primary constructors make intent explicit while keeping type definitions compact.
Use records for data‑centric types that benefit from immutability and equality. For entities with identity and lifecycle, prefer classes and explicitly model invariants.
Pattern Matching Upgrades
Relational, logical, and list patterns enable declarative branching that replaces nested conditionals. Switch expressions express mapping cleanly and are exhaustiveness‑checked by the compiler, improving safety.
Prefer patterns over manual type checks and flag fields. This yields self‑documenting code that’s easier to extend without editing existing branches.
Async/Await and Task‑based APIs
Asynchrony is a core competency in server and UI code. Embrace async/await end‑to‑end; avoid sync‑over‑async and blocking on tasks. Use cancellation tokens and timeouts to guard resources and surface intent to callers.
Design APIs to be naturally asynchronous where I/O is involved, and keep CPU‑bound work off request threads using dedicated queues or background services.
Span<T>, Memory<T>, and Low‑Allocation Techniques
Spans offer safe, stack‑friendly views over contiguous memory for parsing and encoding workloads. Combined with pooling and caching, they significantly reduce GC pressure in hot paths.
Measure before optimizing. Apply spans and pooling to confirmed hotspots, and wrap low‑level code with clear boundaries so most of the codebase remains simple and readable.
Minimal APIs and Source Generators
Minimal APIs streamline HTTP endpoints with low ceremony—ideal for microservices and internal tools. Source generators can eliminate reflection‑heavy plumbing by producing compile‑time mappings and clients.
Balance minimalism with structure: keep domain/application logic outside the endpoint to preserve testability and maintain boundaries.
Required Members, File‑Scoped Types, and Improved Diagnostics
Required members enforce construction contracts, while file‑scoped types and namespaces reduce noise. New analyzers and nullable reference types surface potential defects early in the lifecycle.
Adopt nullable reference types in new code, fix warnings as errors, and treat the compiler as a design partner—it’s the cheapest place to catch mistakes.