Course program← C#: Базовый курс
1Знакомство с C# и .NET
2Данные и типы
3Ветвления и циклы
4Методы и ошибки
5Коллекции и строки
6Классы и объекты

Первая программа

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 – лучший поисковый запрос, чем пересказ проблемы своими словами. По нему находится и официальное описание, и десяток чужих историй с тем же номером.

Исправлять ошибки начинайте всегда с первой. Компилятор после сбоя нередко теряет нить и выдаёт ещё десяток жалоб-последствий: пропущенная скобка легко превращается в пятнадцать сообщений, из которых настоящее – только верхнее.