Understanding the .NET Internal Compile Process

In the .NET platform, we have more than 100 languages. It is a big platform that contains popular languages like C#, F#, VB.NET, etc. You can find the full list of languages Category:.NET programming languages - Wikipedia

The languages we mentioned above, are the most popular ones. The term ‘.NET’ is a runtime that helps us to execute our code written in different .NET languages to a byte code that is possible to compile to machine language.

.NET doesn’t compile the code written in high-level language directly into machine language(CPU understandable instructions). Instead, In the middle, we have a special abstraction that abstracts out our code from concrete hardware.

.NET compilers compile our code into IL instructions

Let's create a simple Console application to prove it.

  1. Open Visual Studio
  2. From the templates -> select the Console application
  3. Provide any name you want
  4. Generate a template

Here is what it looks like

namespace ConsoleApp5
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, World!");
        }
    }
}
  1. Go to Windows search and find the ‘developer command prompt’.
    Developer command prompt
  2. Run ‘ildasm’ to open the Intermediate Language disassembler
  3. Build your application
  4. Open the folder that contains your executable code
  5. Move ‘your_application_name.dll’ file into ildasm
    Intermediate Language disassembler
  6. Now let's try to check the generated IL code.
     Generated IL code

But that is not all. To make sure that we can compile these IL code instructions we need CLR. CLR stands for Common Language Runtime. But this is also another ‘application’ that needs to be triggered to run properly.

There is a process loader that helps us to load CLR into memory. Process loader takes our application and loads it. But that is not all. Before loading there are some additional checks. It should check if it is a valid .NET application by checking the application header and meta information. After all these checks, the process loader triggers CLR and takes control of CLR.

Here are the responsibilities of CLR

  1. Managing and executing the .NET application
  2. Memory allocation
  3. External Assembly management
  4. Security
  5. Exception Handling

One of the Components of CLR is JIT (Just in Time) compiler. JIT compiler takes our IL code and compiles it into native CPU instructions.

Conclusion

.NET is a powerful runtime that helps to develop applications using different programming languages. All these languages' codes end with IL code. JIT Compiler in CLR helps to 'convert' IL code to native machine language.