What is Common Language Runtime (CLR) and why should I learn about it?
Chronicles of .NET Runtime - Part 1
Hi! 👋
I’ve been talking about it for a while now. Given that the last article on C++ and memory allocation went out yesterday, it’s time to start a new chapter and new deep-dive series.
Before I do, I’d like to take a moment and reflect on one thing. And this is something that has been hanging over my head for a while now. If you are just casually scrolling through Bitesized articles, you’d probably think something along the lines of “wow, this guy makes context switches like it’s nothing!”. In a way, you’d be right - I started writing about SQL Server’s Storage Engine Internals, then switched to Containers, then spent some months on DB Indexes, before finally moving to C++ and Memory Allocation. Wanna know how that works and feels?
It sucks. And it scares the shit out of me. Honestly. It is exciting, for sure, because I get to explore cool new things that I’m really interested in, but trust me - it’s scary! Starting ANYTHING new is always scary.
But here’s the gist - I learned that after two or three articles it becomes a breeze and then it just starts flowing. Really. So I just need to survive to break the ice of the new topic and then I’m sure it will get easier :)
Anyway, I just wanted to share those thoughts with you. Back to the original topic - CLR. As usual, the infographic first and then we go with some more detailed explanation!
I hope you found that useful :)
Let’s start from the beginning - do you need to know about CLR in order to use C# (or any other .NET based language)? No.
So why SHOULD YOU spend time on it? In my opinion - for the same reason you decide to learn anything - once you understand the internals, you get a whole new perspective on how to write more performant and reliable code.
Back to the topic, though. So, what’s the Common Language Runtime (CLR )? Well, it’s the Runtime Engine for .NET. Just like JVM is for Java. It makes your .NET code actually DO stuff. But there’s a lot more to it.
All your .NET code compiles into something that is, these days, referred to as Microsoft’s Intermediate Language (MSIL). Here’s a very simple app:
namespace SampleCSharpApp2
{
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello, World!");
}
}
}
And here’s the MSIL code that was generated for it (hint: .NET bundles an app called ILDASM.exe - an IL Dissasembler; search for it in your .NET directory):
.class private auto ansi beforefieldinit Program
extends [System.Runtime]System.Object
{
.custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.method private hidebysig static void '<Main>$'(string[] args) cil managed
{
.entrypoint
// Code size 12 (0xc)
.maxstack 8
IL_0000: ldstr "Hello, World!"
IL_0005: call void [System.Console]System.Console::WriteLine(string)
IL_000a: nop
IL_000b: ret
} // end of method Program::'<Main>$'
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [System.Runtime]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method Program::.ctor
} // end of class Program
If you’ve never encountered it before - that’s OK. It might take a moment or two to get adjusted to it. What you are looking at is disassembled MSIL code :) It looks like assembly, but it’s way more readable and understandable. Well, for contrast, here’s an actual assembly code for the same thing:
You have to agree that MSIL is a “bit” more understandable, right?
Anyway, we’ll talk lot more about MSIL in the upcoming articles. And if you haven’t subscribed already, now’s a good time to do so:
The whole point of MSIL and CLR is that you can run it on any architecture and any platform. And that’s made possible by the fact that MSIL is being interpreted by CLR, which takes those instructions, compiles them to native-code for the target platform (e.g. if you are executing the code above on Linux, it’d be compiled to Linux’s native code) and executes them. This process of compiling just before executing is called JIT Compilation (Just In Time Compilation). It has some pros & cons but we’ll also spend some time discussing that in future articles. What’s important to remember for now is that CLR compiles the code to machine-readable language, whereas Java interprets the code and emulates it through Java’s VM. Again, don’t worry too much about it for now - it’ll become more clear as we progress.
What’s uniquely cool about MSIL is that, strictly speaking, you are NOT limited to C#, F#, VB, etc. As long as you write a program that takes ANY source code (e.g. Python, PHP, C++, etc.) and converts it to MSIL - you can have it run on CLR. And people actually did just that:
IronPython compiles Python to CLR
PeachPie compiles PHP to CLR
Managed C++ compiles C++ into MSIL
Windows’ PowerShell was built on top of CLR
etc.
I hope you got the idea so far :) MSIL is awesome and we’ll definitely talk much more about it in upcoming articles.
And this is where I’ll stop for today. I hope that this article gave you an idea of what’s coming. And trust me - a LOT MORE interesting stuff is about to come throughout the following weeks! Next time I will be talking about Assemblies, the fundamental unit of deployment for CLR.
Until then!
P.S. If you enjoyed this article, do consider sharing it:
Thanks for reading!
Other articles in this series: