This lesson is not translated yet – the Russian original is below.
Традиция требует, чтобы первая программа поздоровалась с миром. Не будем спорить с традицией – тем более что на этих трёх строчках видно почти всё устройство языка.
Самый короткий вариант
Создайте файл Program.cs и напишите в нём одну строку:
Console.WriteLine("Привет, мир!");
Это законченная программа. Запустится, выведет текст, завершится.
Разберём её по частям, потому что здесь нет ни одного случайного символа:
Console– класс из библиотеки .NET, отвечающий за консоль: он умеет писать в неё и читать из неё;WriteLine– метод этого класса: «напиши строку и переведи каретку на новую»;"Привет, мир!"– значение, которое мы передаём методу. Текст в C# всегда в двойных кавычках, одинарные заняты под одиночные символы;;– точка с запятой, конец команды. Не украшение: компилятор по ней понимает, где кончается одна инструкция и начинается следующая.
C# различает регистр. Console и console – два разных имени, и второго не существует. Ошибка компилятора будет звучать как «имя не найдено в текущем контексте», хотя визуально всё написано правильно.
Почему у других языков этой строки хватает, а у C# – не всегда
Тот же вывод на трёх языках. Обратите внимание не на текст, а на количество обвязки вокруг него:
Console.WriteLine("Привет, мир!");
print("Привет, мир!")
#include <iostream>
int main() {
std::cout << "Привет, мир!" << std::endl;
return 0;
}
Разница не в многословности языка, а в том, кто отвечает за подготовку. В Python интерпретатор сам решает, откуда начать. В C++ нужно вручную объявить точку входа и подключить нужный заголовок. C# до 2021 года требовал примерно того же, что и C++, а потом обзавёлся коротким вариантом – но старый никуда не делся, и в чужом коде вы увидите именно его.
Развёрнутый вариант: то же самое, но честно
Вот что компилятор на самом деле собирает из нашей единственной строки:
using System;
namespace HelloWorld
{
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine("Привет, мир!");
}
}
}
Здесь семь строк вместо одной, и каждая отвечает на свой вопрос.
using System; – подключение пространства имён. Полное имя класса консоли – System.Console.
Строчка using разрешает не писать System. каждый раз. Это не импорт файла и не копирование
кода: библиотека уже подключена, using лишь избавляет от приставки.
namespace HelloWorld – пространство имён вашего кода. Способ избежать столкновения имён:
классы MyCompany.Logger и OtherCompany.Logger спокойно живут в одной программе.
class Program – класс. В C# любой код обязан лежать внутри класса; свободно висящих функций
в языке нет. Пока считайте класс просто ящиком, куда складывают методы, – подробный разбор будет
в шестом модуле.
static void Main(string[] args) – точка входа. Именно отсюда начинается выполнение. Если
такого метода нет, компилятор скажет, что программа не содержит точки входа.
Разберём заголовок Main по словам:
| Часть | Что означает |
|---|---|
static |
метод принадлежит классу, а не объекту: чтобы вызвать Main, объект создавать не надо |
void |
метод ничего не возвращает |
Main |
имя точки входа, зарезервировано по соглашению, именно с большой буквы |
string[] args |
аргументы командной строки: то, что дописали после имени программы при запуске |
Так какой вариант писать
Короткий вариант называется top-level statements – «инструкции верхнего уровня». Компилятор
сам заворачивает их в класс с Main, поэтому это не другой способ запуска программы, а другой
способ записи того же самого.
Инструкции верхнего уровня разрешены только в одном файле проекта. Иначе получилось бы две точки входа, и компилятор не смог бы выбрать, с какой начинать.
В курсе мы будем писать коротко: меньше строк, не относящихся к теме урока. Но развёрнутый вид надо уметь читать – в реальных проектах и в примерах из интернета он встречается постоянно.
Фигурные скобки и отступы
Блок кода в C# ограничен фигурными скобками { и }. Тело метода, тело класса, тело цикла –
всё это блоки.
Отступы на смысл не влияют: компилятору всё равно, сколько пробелов слева. Программу можно записать в одну строку, и она соберётся. Но читать её будете вы, поэтому в C# принято ставить открывающую скобку на новой строке и отступать содержимое блока на четыре пробела.
Не расставляйте отступы вручную. В Visual Studio и Rider форматирование по умолчанию висит на Ctrl+K, Ctrl+D, в VS Code – Shift+Alt+F, а dotnet format приводит в порядок весь проект целиком.
Комментарии
Текст для человека, который компилятор пропускает:
// Однострочный комментарий: до конца строки
/* Многострочный:
годится, когда пояснение не помещается в строку */
/// <summary>
/// Документирующий комментарий. Редактор показывает его во всплывающей
/// подсказке при вызове метода.
/// </summary>
Комментарий, который пересказывает код словами, бесполезен: // увеличиваем i на единицу рядом с
i++ не добавляет ничего. Полезный комментарий отвечает на вопрос «почему», а не «что»:
«отступ в 200 мс – требование стороннего API, без него он отвечает 429».
Что делать с ошибками компилятора
Ошибку вы увидите раньше, чем запустите программу: подчёркиванием в редакторе и строкой в терминале.
Program.cs(3,1): error CS1002: ; expected
Читается это так: файл Program.cs, строка 3, символ 1, код ошибки CS1002, а дальше суть –
ожидалась точка с запятой.
Код вида CS1002 – лучший поисковый запрос, чем пересказ проблемы своими словами. По нему находится и официальное описание, и десяток чужих историй с тем же номером.
Исправлять ошибки начинайте всегда с первой. Компилятор после сбоя нередко теряет нить и выдаёт ещё десяток жалоб-последствий: пропущенная скобка легко превращается в пятнадцать сообщений, из которых настоящее – только верхнее.