You compile your code to IL which gets executed and compiled to machine code during runtime, this is what's called JIT.
Edit, to flesh out the answer some more (still overly simplified):
When you compile your C# code in visual studio it gets turned into IL that the CLR understands, the IL is the same for all languages running on top of the CLR (which is what enables the .NET runtime to use several languages and inter-op between them easily).
During runtime the IL is interpreted into machine code (which is specific to the architecture you're on) and then it's executed. This process is called Just In Time compilation or JIT for short. Only the IL that is needed is transformed into machine code (and only once, it's "cached" once it's compiled into machinecode), just in time before it's executed, hence the name JIT.
This is what it would look like for C#
C# Code >
C# Compiler >
IL >
.NET Runtime >
JIT Compiler >
Machinecode >
Execution
And this is what it would look like for VB
VB Code >
VB Compiler >
IL >
.NET Runtime >
JIT Compiler >
Machinecode >
Execution
And as you can see only the two first steps are unique to each language, and everything after it's been turned into IL is the same which is, as I said before, the reason you can run several different languages on top of .NET
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…