The CLI, the CLR and compilation

1 min read

The .NET platform has evolved significantly. .NET Core (now simply .NET 5 and later) is a modular, cross-platform, high-performance successor to the traditional .NET Framework.

CLI: the Common Language Infrastructure

The CLI is an ECMA standard that specifies a language-neutral platform for developing and executing applications. .NET is an implementation of this standard. It defines aspects like the Common Type System (CTS), the Common Language Specification (CLS), and the format of metadata.

CLR: the Common Language Runtime

The CLR is the execution engine for .NET applications. It provides essential services: memory management (including garbage collectionGarbage collection and generationsThe runtime frees memory for you, sorted by how long objects live.Opens in a new tab), Just-In-Time (JIT) compilation of CIL to native code, type safety verification, exception handling, security and thread management.

CoreCLR is the specific CLR implementation for .NET (Core) and later versions (.NET 5+). It is open source and designed to be cross-platform, running on Windows, macOS and various Linux distributions.

Managed code

Code written in languages like C#, F# or VB.NET that targets the .NET runtime is compiled into Common Intermediate Language (CIL) and executed under the management of the CLR. The CLR handles tasks like object lifetime and memory allocation for this managed code.

The compilation process

Source code, for example C#, is first compiled by a language-specific compiler (like Roslyn for C#) into CIL, also known as Microsoft Intermediate Language (MSIL). This CIL, along with metadata, is stored in assembliesProject structure and assembliesWhat a .NET solution is made of on disk, and what the build produces.Opens in a new tab (DLL or EXE files).

At runtime, the CLR’s JIT compiler converts the CIL into native machine code for the underlying hardware architecture, just before execution.

Native AOT skips that last step. It compiles the application to native code ahead of time, so there is no JIT at runtime. That is also why code that depends on reflection can break under Native AOT, and why source generatorsSource generators versus reflectionA source generator does at build time what reflection does at runtime.Opens in a new tab matter.


Sources