В чём разница между CIL (MSIL) и обычным кодом C#?
Прочитал, что C# компилируется в какой-то CIL (он же MSIL). Чем этот промежуточный язык отличается от моего исходника на C# и от машинного кода? Зачем вообще нужен лишний слой?
2 ответа
Есть три уровня, и важно их не путать:
- Исходный код C# — то, что пишете вы, человекочитаемый текст.
- CIL / MSIL (Common Intermediate Language, бывш. Microsoft Intermediate Language) — низкоуровневый, но всё ещё платформонезависимый байт-код. В него компилятор
cscпереводит ваш C#. - Машинный код — нативные инструкции конкретного процессора. В него CIL превращает JIT уже во время запуска.
Зачем промежуточный слой:
- Платформонезависимость — одна и та же сборка с CIL запускается на x64, ARM, Linux, Windows. Под архитектуру код доводит JIT на месте.
- Языконезависимость — C#, F#, VB.NET компилируются в один и тот же CIL, поэтому сборки на разных языках спокойно вызывают друг друга.
Посмотреть CIL можно дизассемблером ildasm (или утилитой dotnet-ildasm). Условный int x = 2 + 3; превратится во что-то вроде:
ldc.i4.2
ldc.i4.3
add
stloc.0
Это стек-ориентированные команды: «положи 2», «положи 3», «сложи», «сохрани в локальную переменную». Процессор такое напрямую не исполняет — сначала JIT, потом нативный код.
Аналогия: C# — это как текст на русском, CIL — как универсальный подстрочник, а машинный код — перевод под конкретного слушателя. Подстрочник нужен, чтобы один раз скомпилировать, а потом запускать где угодно: финальный «перевод» (JIT) делается уже на целевой машине.