Процесс Компиляции C# И Common Intermediate Language (Cil)

Скачать

Процесс компиляции C# и Common Intermediate Language (CIL)

Что такое CIL?

CIL (Common Intermediate Language) — это промежуточный язык, в который компилируется исходный код C# перед выполнением. Он стандартизирован в рамках CLI (Common Language Infrastructure) и раньше назывался MSIL (Microsoft Intermediate Language).

Программы на C#, VB.NET, F#, и других языках .NET сначала компилируются в CIL, а не напрямую в машинный код.


Этапы компиляции C# программы

1. Написание кода

Код пишется на C# в файле с расширением .cs.

class Program {
    static void Main() {
        Console.WriteLine("Hello, world!");
    }
}

2. Компиляция в CIL (файлы .dll или .exe)

С помощью компилятора csc (C# Compiler) код преобразуется в CIL, который сохраняется в сборке — файле .dll (библиотека) или .exe (исполняемый файл).

csc Program.cs
# Создаст Program.exe

На этом этапе код ещё не исполняется. Он просто хранится в виде CIL-инструкций в сборке.


3. Загрузка CLR и JIT-компиляция

Когда ты запускаешь .exe или подключаешь .dll:

  • .NET CLR (Common Language Runtime) загружает сборку.
  • JIT-компилятор (Just-In-Time) преобразует CIL в машинный код, который понимает конкретный процессор (x64, ARM и т.д.).
  • После этого программа выполняется.

.NET 6+ может использовать ReadyToRun (R2R) или AOT (Ahead-of-Time) компиляцию, чтобы ускорить запуск.


Что находится внутри .dll и .exe сборок?

Компонент Описание
CIL-код Промежуточный код, который исполняется CLR через JIT-компиляцию
Метаданные Информация о типах, методах, свойствах, пространствах имён и т.п.
Манифест сборки Информация о версии, зависимостях, культуре, имени сборки и т.п.
Ресурсы (опц.) Встроенные изображения, строки, локализация и другие данные
Символы отладки (если присутствует .pdb) — соответствие строк кода и CIL-инструкций

Пример: как выглядит CIL

Пример C#:

int Add(int a, int b) => a + b;

CIL (упрощённо):

.method public hidebysig static int32 Add(int32 a, int32 b) cil managed
{
    .maxstack 2
    ldarg.0
    ldarg.1
    add
    ret
}

ldarg.0 — загрузка первого аргумента на стек
add — сложение двух верхних значений на стеке
ret — возврат результата


Какие технологии взаимодействуют с CIL?

Технология Роль в процессе
Roslyn Компилятор C#, генерирует CIL
CoreCLR / CLR Исполняет CIL, использует JIT
ILDasm Разборщик: показывает CIL из сборки
ILSpy, dnSpy Декомпиляторы: показывают CIL и C#
Mono Кроссплатформенная реализация CLR
dotnet publish Компиляция и упаковка для публикации

Почему используется CIL?

  • ✅ Независимость от архитектуры: один .dll или .exe может выполняться на разных системах
  • ✅ Поддержка многих языков (VB.NET, F#, C++/CLI) в рамках одного рантайма
  • ✅ Оптимизация на стадии JIT под конкретную платформу

Резюме

Этап Что происходит
1 Код пишется на C#
2 Компилируется в CIL → .dll/.exe
3 CLR загружает сборку
4 JIT преобразует CIL в машинный код
5 Код исполняется на системе

Полезные команды

# Посмотреть CIL код
ildasm Program.exe

# Декомпиляция через ILSpy
ilspy Program.dll

# Компиляция проекта
dotnet build

# Публикация со сборкой ReadyToRun
dotnet publish -r win-x64 -p:PublishReadyToRun=true

Полезные ссылки