C# & .NET
Begin with one small C# program that reads values, makes a decision, and prints an exact result. Learn what the .NET runtime does, what a type protects, how a method receives and returns data, and how objects hold related state before using larger libraries. Collections, query syntax, files, errors, asynchronous work, and concurrency are introduced through visible problems one at a time. Web services, durable data, measurement, packaging, and deployment come later, with each local result clearly separated from evidence still required in a real production environment.
.NET toolchain, projects, and execution
Objective Build and inspect a reproducible C# program with a declared SDK, target framework, and artifact identity.
Core explanation
C# source is compiled by the .NET SDK into assemblies containing Common Intermediate Language and metadata, then executed by a compatible .NET runtime with just-in-time or ahead-of-time compilation according to the publish mode. The project file declares target framework, language and nullable policy, references, resources, analyzers, and build behavior. Use a global.json only when the repository needs an SDK selection rule, restore from a lock-aware dependency policy, and distinguish build, run, test, pack, and publish outputs. C# 14 and .NET 10 are the current baseline for this course, but production work must track the support policy rather than assuming the newest installed SDK is the deployed runtime.
Establish the C# and .NET contract for .NET toolchain, projects, and execution
Distinguish C# language version, target framework moniker, SDK selection, runtime, base class library, project and solution, build configuration, dependency graph, assembly metadata, application host, and publish mode. A file-based C# 14 program is convenient for exploration, while a maintained product still needs tracked project and release contracts. For a reproducible inspected C# release, write a contract table containing domain meaning, C# static guarantee, CLR or library runtime behavior, external precondition, owner, resource limit, error, and terminal outcome. A beginner should be able to trace a value without relying on an editor tooltip or a slogan imported from another language.
Trace source through restore, Roslyn compilation, generated inputs, metadata and IL, linking, runtime configuration, loader, JIT or AOT, process startup, and shutdown. Framework-dependent, self-contained, single-file, trimmed, ReadyToRun, and native AOT artifacts make different compatibility, size, reflection, and deployment promises. Draw the source, generated code, assembly, object, thread or task, native or operating-system, storage, network, and deployment boundaries involved. Mark which facts the compiler proves, which the runtime checks, which the application validates, and which remain an operational or product promise.
Design and implement a reproducible inspected C# release
Declare supported SDK and runtime policy, central or project packages, nullable and analyzer settings, deterministic public configuration, clean build and publish commands, target platform matrix, generated-source ownership, symbols, SBOM, and artifact identity. Keep secrets and machine-local paths outside compiled and published output. Build one transparent vertical slice before adding framework convenience. Give every value, collaborator, resource, task, transaction, callback, package and configuration input an explicit owner and lifetime; represent validation, cancellation, conflict, denial and uncertainty rather than collapsing them into null or a generic exception.
Use the maintenance change “add a second supported runtime identifier without hidden machine or workload state” as the running trace through a reproducible inspected C# release. Before coding, record the initial domain facts and the observable result that a caller needs; at each boundary, identify the value representation, responsible owner, permitted authority, finite resource budget, durable effect and recovery decision. Then provoke “An editor run succeeds while the clean publish uses a different SDK, floating package, generated file, target runtime, native dependency, configuration, or entry point and cannot reproduce the deployed bytes.” and compare the earliest divergent state with the successful trace. Preserve the chapter-specific compiler output, generated input, runtime object, task schedule, protocol exchange, stored record, package fact or operational signal that actually decides the outcome.
Diagnose failures and prove .NET toolchain, projects, and execution
Run restore, format or analyzers, tests, Release build and publish in an isolated directory; inspect project evaluation, resolved packages, assembly and runtime configuration, dependencies, generated files, symbols, file type, runtime output, and hashes. Rebuild from the same inputs and investigate meaningful differences. Preserve the exact SDK, dependency graph, source revision, configuration class, test input, schedule, database generation, package and symbols needed to reproduce the claim. Combine focused assertions with an independent boundary or artifact check so source-level intention cannot silently diverge from the bytes and runtime under review.
The diagnostic counterexample is: An editor run succeeds while the clean publish uses a different SDK, floating package, generated file, target runtime, native dependency, configuration, or entry point and cannot reproduce the deployed bytes. Minimize it, identify the first violated language, type, lifetime, concurrency, I/O, authorization, transaction, compatibility or capacity invariant, and repair that boundary. Re-run normal, empty, maximum, malformed, concurrent, cancelled, crashed, upgraded and restored cases rather than approving only the final symptom.
Laboratory: build a reproducible inspected C# release
Create a reproducible inspected C# release from a clean repository with nullable warnings and selected analyzers enforced. Begin with the contract encoded by Distinguish C# language version, target framework moniker, SDK selection, runtime, base class library, project and solution, build configuration, dependency graph, assembly metadata, application host, and publish mode. A file-based C# 14 program is convenient for exploration, while a maintained product still needs tracked project and release contracts. Trace source through restore, Roslyn compilation, generated inputs, metadata and IL, linking, runtime configuration, loader, JIT or AOT, process startup, and shutdown. Framework-dependent, self-contained, single-file, trimmed, ReadyToRun, and native AOT artifacts make different compatibility, size, reflection, and deployment promises. Declare supported SDK and runtime policy, central or project packages, nullable and analyzer settings, deterministic public configuration, clean build and publish commands, target platform matrix, generated-source ownership, symbols, SBOM, and artifact identity. Keep secrets and machine-local paths outside compiled and published output. Implement the smallest correct core, real boundary adapter and composition root; include deterministic fixtures, a deliberate failing mutation, privacy-safe diagnostics, capacity and exact publish commands.
Acceptance requires another maintainer to reproduce “An editor run succeeds while the clean publish uses a different SDK, floating package, generated file, target runtime, native dependency, configuration, or entry point and cannot reproduce the deployed bytes.”, explain the earliest invalid state, apply and verify the repair, publish the exact artifact, and then add a second supported runtime identifier without hidden machine or workload state. Deliver diagrams, source and project inputs, tests, traces, package hashes and symbols, limits, compatibility matrix, rollback or repair, restore and reconciliation evidence, and a concise ownership runbook.