Course outline

C# / Basic: Typed Programs and Object Contracts / Lesson 1

The C# Toolchain and Program Model

Distinguish the language, compiler, runtime, and libraries while building a reproducible console application.

About 5 min readContent reviewed
On this page

Lesson goals

  • Explain SDK, target framework, language version, and CLR.
  • Read a complete console entry point.
  • Record build inputs and interpret diagnostics by phase.

Language and runtime are separate layers

C# specifies language rules such as types, expressions, and control flow. The compiler translates source into an assembly containing intermediate language and metadata. The common language runtime loads and executes managed code, commonly using just-in-time compilation; ahead-of-time deployment is another explicit configuration. Platform libraries provide Console, collections, tasks, and I/O. None of these layers is identical to an ASP.NET application framework.

The .NET SDK contains development tools, while the target framework declares the library/runtime surface a project expects. A machine can have several SDKs and runtimes. Record the actual SDK used instead of inferring it from the target framework or an IDE label.

A complete source has an entry path

The first example uses an explicit Program class and static Main method. This form makes the entry point visible without relying on template-generated source. A using directive makes a namespace’s type names convenient; it does not download a package or create an object. Console.WriteLine writes the supplied string and a line ending.

Top-level statements are an alternative entry-point syntax supported by the course baseline. They do not remove compilation or create several independent entry points. Keep independent examples in separate temporary projects, because combining complete examples can introduce conflicting Program or Main declarations.

csharp An explicit console entry point
using System;

internal static class Program
{
    private static void Main()
    {
        Console.WriteLine("C# ready");
    }
}
Expected output
C# ready

Main calls a platform-library operation; the program creates no background work or external connection.

Make the project contract explicit

This course uses net10.0, LangVersion14.0, and nullable analysis enabled. The SDK and runtime have their own patch versions. Do not select latest or preview merely to silence a syntax error: that can change accepted features across developer machines. A global.json can select an SDK for a repository, but a lesson must not silently change a user’s global defaults.

Standard-library examples need no third-party NuGet packages. An isolated verification project can clear package sources and use SDK-provided framework packs. Real package restoration is a separate dependency action that should have trusted sources and recorded versions. Successful restoration alone does not prove program correctness.

Trace state through complete statements

A variable holds a value of its declared type. In the second example count begins at two, an assignment replaces it with five, and interpolation reads the resulting value. Assignment changes storage; it is not an assertion of mathematical equality. These small integer operations fit the type without any overflow issue.

The explanation needs no claim about a physical stack slot or one machine instruction per source statement. The compiler and runtime can optimize storage while preserving defined observable behavior. Later lessons distinguish value copying from shared object references, which is more useful than guessing addresses.

csharp Observe a completed assignment
using System;

int count = 2;
count = count + 3;
Console.WriteLine($"count={count}");
Expected output
count=5

The top-level program computes five before formatting the line.

Use diagnostics as evidence

A syntax or type error belongs to compilation; a missing assembly or unavailable runtime can appear during loading or launch; a wrong result is a behavioral failure. Nullable warnings reveal possible contract mismatches even when a build succeeds. Treat the first relevant diagnostic as a starting point rather than suppressing a whole category to make the output look clean.

For a reproducible report, include the small source, project properties, SDK version, exact command, input, and expected versus observed output. Confirm that the executable belongs to the latest successful build. A stale artifact or another startup project can make a correct source change appear ineffective.

Common errors and fixes

A language feature appears unsupported.

Why it happens
The project selects another language version or SDK.
How to fix it
Inspect project properties and the selected SDK before changing syntax.
Prevent it next time
Record an explicit baseline.

Independent examples conflict when combined.

Why it happens
They define multiple entry paths or duplicate types.
How to fix it
Use one temporary project per complete program.
Prevent it next time
Treat each displayed example as an independent command.

A successful build still launches old behavior.

Why it happens
The wrong startup project or stale artifact is used.
How to fix it
Verify the output path and rebuild the intended project.
Prevent it next time
Keep build and run commands paired.

Check your understanding

1. Predict the second example when count starts at four and the assignment adds seven. State which assumptions are necessary.

Show worked solution

The initializer stores four, assignment computes eleven, and interpolation prints count=11 followed by a newline. The values are representable int values and the statements execute in order. No platform-specific address, runtime optimization, or user input is involved. The top-level syntax changes presentation of the entry point, not these arithmetic semantics.

2. Why is TargetFramework net10.0 insufficient to record every input needed for a reproducible build?

Show worked solution

It names the target API/runtime family, not the exact SDK, language override, dependency graph, build configuration, generated files, or platform-specific deployment settings. Record relevant project properties and SDK selection as well. For these platform-library-only console examples, clearing external sources and using an isolated project removes many unrelated variables.

Key takeaways

  • C#, the SDK, the runtime, and application frameworks are different layers.
  • Pin meaningful project inputs instead of assuming latest behavior.
  • A successful build and a correct result are separate claims.

Official references