$ dotnet new console$ dotnet runHello, WorldWindowsx64macOSArm64Linuxx64CPUCLR · common language runtimeJITheapfree"Hello, World"msg · string1var name = "World";2var msg = "Hello, " + name;3Console.WriteLine(msg);RoslynHello.dll1ldstr "World"2ldstr "Hello, "3call String::Concat4call Console::WriteLine5retIL0101msg
Front row: build time (C# → Roslyn → IL in an assembly)Back row: run time (the CLR, the CPU and the console)Tokens: C#, IL, the assembly, machine code and the string msg moving throughFront row, build time: your C# in Program.cs, the compiler Roslyn, and the assembly Hello.dll holding IL. Back row, run time: the CLR with its JIT compiler and the heap, the CPU, and the console. dotnet run builds (C# → IL), then the CLR JIT-compiles the IL to machine code, the CPU runs it, a new string lands on the heap, Hello, World reaches the console, and the garbage collector frees the string. The IL card is shortened but in the real order. The full Debug listing also stores and loads the two locals (stloc, ldloc), has a few nop instructions, and names each method in full, such as System.String::Concat(string, string).

C# and .NET

  1. C# (say "see sharp") is a modern programming language from Microsoft. It is type-safe: every value has a type, such as string or int, and the compiler stops code that mixes them up. C# programs run on .NET.

Build: C# to IL

Run: the CLR

What happens

// step 1/11 · csharp
C#          a programming language from Microsoft (first released 2002;
            standard ECMA-334)
type-safe   every value has a type: "World" is a string, 2 is an int
            the compiler rejects code that mixes them up
runs on     .NET

The IL card is shortened but in the real order. The full Debug listing also stores and loads the two locals (stloc, ldloc), has a few nop instructions, and names each method in full, such as System.String::Concat(string, string). Real .NET uses tiered compilation: a quick first compile, then a better one for methods that run often. Much of the .NET library ships already compiled (ReadyToRun), so the JIT mostly compiles your own methods.