Part 4 · 1 chapters · ~8 min
Idioms
Nullable reference types and warnings as errors, records versus classes, constructor injection and service lifetimes (captive dependencies), exceptions versus result types, LINQ readability and deferred execution pitfalls, IDisposable patterns, naming conventions, .editorconfig and Roslyn analyzers, and common review comments.
5
Patterns that age well
code
<PropertyGroup>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<AnalysisLevel>latest-recommended</AnalysisLevel>
</PropertyGroup>
builder.Services.AddScoped<ILedger, Ledger>(); // per request
builder.Services.AddSingleton<IFxRates, CachedFxRates>(); // must not depend on scoped services (captive dependency)
// deferred execution: this query runs twice
var pending = db.Payouts.Where(p => p.State == "pending");
if (pending.Any()) foreach (var p in pending) … // two round trips; use ToListAsync once
public abstract record TransferResult { public sealed record Ok(Transfer T) : TransferResult; public sealed record InsufficientFunds(long Available) : TransferResult; }IDIOMATIC C#
what reviewers look for
swipe the figure sideways, or tap expand for full screen
1/4
safety settings
Enable nullable reference types and treat warnings as errors in new projects; most null bugs then fail the build.
nullable + warnings as errorsbugs at build time