Программа и компилятор
Чему вы научитесь:
- объяснять, как текст программы на C# становится работающей программой;
- печатать текст через
Console.WriteLineиConsole.Writeи предсказывать, где окажется каждая строка вывода; - читать сообщение компилятора и исправлять ошибку, которую он нашёл;
- отличать инструкции верхнего уровня от классического метода
Main.

Программа — это рецепт для компьютера. В рецепте шаги записаны по порядку, и повар выполняет их один за другим, сверху вниз. Компьютер работает так же, только без догадок. Повар поймёт «посолить по вкусу», а компьютер сделает ровно то, что написано, и ничего сверх этого.
Рецепт для компьютера пишут обычными буквами в обычном текстовом файле. Файлы с программами на C# получают расширение .cs. Вот текст целой программы — она состоит из одной строки и печатает приветствие:
Console.WriteLine("Hello, World!"); // Hello, World!Текст после // — комментарий: пометка для людей, на работу программы она не влияет. В примерах курса такой комментарий показывает, что напечатает строка, а знак ✗ в комментарии отмечает строку с ошибкой.
Есть одна сложность: процессор не читает буквы. Процессор — это часть компьютера, которая выполняет команды. Понимает он только машинный код: длинные цепочки чисел, и у каждого вида процессоров они свои. Поэтому текст программы нужно перевести, и в C# этот перевод идёт в два этапа.
Компилятор — строгий корректор
Первый этап — компилятор: программа, которая сверяет текст с правилами языка и переводит его на язык, более близкий к машинному. Представьте строгого корректора, который читает рецепт целиком, прежде чем тот попадёт на кухню.
Корректор работает по двум правилам:
- если в тексте нарушено хоть одно правило языка, он возвращает текст с пометками: в каком файле, в какой строке и что не так;
- пока ошибка не исправлена, на кухню рецепт не попадёт, и не выполнится ни один шаг, даже написанный верно.
Здесь картинка с корректором перестаёт работать. Настоящий корректор заметил бы опечатку в слове, а компилятор следит только за правилами языка и не вникает в смысл. Если написать "Helo, World!", программа запустится, и опечатку вы увидите только в том, что она напечатает.
Промежуточный язык IL
Компилятор C# не переводит текст сразу в машинный код вашего процессора. Он переводит его в промежуточный язык IL — набор команд для воображаемого универсального процессора — и записывает результат в файл с расширением .dll.
Зачем нужен промежуточный шаг? Компьютеры бывают разными:
- в ноутбуках чаще всего стоят процессоры Intel и AMD, а в телефонах и новых Mac — процессоры ARM, и машинный код у них разный;
- на одних компьютерах стоит Windows, на других — Linux или macOS, а одна и та же программа должна работать на всех.
Один и тот же файл с IL запускается на любом из этих компьютеров, если на нём есть .NET — платформа Microsoft, на которой работают программы на C#. Это как рецепт, переписанный условными значками: его поймёт повар на любой кухне мира, а плита, как и процессор, по значкам готовить не умеет.
Среда выполнения .NET
Второй этап — среда выполнения .NET: программа, которая загружает файл .dll, переводит IL в машинный код именно этого процессора и запускает его. Переводит она не заранее, а прямо во время работы: каждый кусок программы — перед тем, как он понадобится впервые. Такой перевод «точно в срок» называют JIT-компиляцией.
Весь путь от текста до работающей программы выглядит так:
- Вы пишете текст программы в файле
hello.cs. - Компилятор C# проверяет текст, переводит его в IL и записывает результат в файл
.dll. - Среда выполнения .NET загружает этот файл и переводит IL в машинный код вашего процессора.
- Процессор выполняет машинный код, и программа печатает
Hello, World!.
На собеседовании об этом пути часто спрашивают так: как код на C# становится работающей программой? Хороший ответ называет все четыре звена этого пути: компилятор, IL в файле .dll, JIT-компиляцию в среде выполнения и машинный код.
Запуск через dotnet run
Компилятор, среда выполнения и команда dotnet, которая управляет ими обоими, устанавливаются одним набором — .NET SDK. Чтобы запустить программу, сделайте три шага:
- Сохраните текст программы в файл
hello.cs. - Откройте окно для текстовых команд — терминал — в папке с этим файлом. В VS Code откройте эту папку и выберите в меню «Терминал» → «Создать терминал»: терминал откроется сразу в ней.
- Наберите команду
dotnet run hello.cs.
Команда передаст файл компилятору и, если ошибок нет, сразу запустит результат в среде выполнения. Файл .dll при этом появится не рядом с hello.cs, а в отдельной папке, которую .NET заводит для таких программ. Если же компилятор нашёл ошибку, команда напечатает её и ничего не запустит.
Частая ошибка
В терминале набрали dotnet run и забыли имя файла:
Couldn't find a project to run.Когда имя файла не указано, команда ищет в папке файл проекта: в нём хранят настройки программы. Программы этого курса обходятся без него, поэтому команда печатает это сообщение и ничего не компилирует. На компьютере с русским интерфейсом оно начинается словами Не удалось найти выполняемый проект.
Наберите команду целиком: dotnet run hello.cs. То же сообщение появится, если терминал открыт не в той папке, где лежит hello.cs.
Главное
- Компилятор проверяет весь текст программы до запуска: при ошибке не выполняется ни одна строка.
- Компилятор C# переводит текст в промежуточный язык IL и записывает его в файл
.dll. - Среда выполнения .NET переводит IL в машинный код во время работы программы — это JIT-компиляция.
dotnet run hello.csкомпилирует файл и сразу запускает программу.