Метод – это кусок кода с именем. Пока программа умещается в двадцать строк, методы кажутся лишней церемонией. Как только строк становится двести, без них не разобраться.
Зачем они
Три причины, и только первая очевидна.
Не повторяться. Один и тот же расчёт в трёх местах – это три места, где придётся исправлять ошибку. Метод делает его одним.
Дать имя. if (age >= 18 && hasPassport && !isBlocked) требует расшифровки. if (CanRegister(user)) – нет. Имя метода объясняет смысл проверки лучше комментария, потому что не
может устареть незаметно.
Разделить задачу. Метод на десять строк можно проверить и понять целиком. Метод на триста строк никто не держит в голове полностью – его читают кусками и в этих кусках ошибаются.
Как объявить
static int Sum(int a, int b)
{
return a + b;
}
Разберём заголовок по частям:
| Часть | Что означает |
|---|---|
static |
метод принадлежит классу, а не объекту. Пока все наши методы такие |
int |
тип возвращаемого значения |
Sum |
имя. Пишется с большой буквы – это соглашение C# |
(int a, int b) |
параметры: что метод принимает |
Вызов выглядит так:
int result = Sum(3, 5); // 8
Console.WriteLine(Sum(1, 2)); // можно сразу в аргумент
Слово static здесь не украшение. Без него метод пришлось бы вызывать через объект, а объектов у нас пока нет. Что оно означает по-настоящему, разберём в модуле про классы.
return
return делает две вещи сразу: отдаёт значение и немедленно завершает метод. Всё, что стоит
ниже, не выполнится:
static string Check(int age)
{
if (age < 0)
{
return "Так не бывает";
}
if (age < 18)
{
return "Несовершеннолетний";
}
return "Совершеннолетний";
}
Здесь три return, и это нормально. Ранние выходы для особых случаев читаются лучше, чем одна
вложенная лесенка if-else на весь метод.
Компилятор следит, чтобы значение возвращалось по любому пути. Уберите последнюю строку – получите ошибку «не все пути кода возвращают значение».
Методы без результата
Когда метод нужен ради действия, тип возврата – void:
static void Greet(string name)
{
Console.WriteLine($"Привет, {name}!");
}
Такой вызов нельзя присвоить переменной – присваивать нечего. return внутри void тоже
допустим, но без значения: он просто досрочно завершает метод.
static void PrintIfPositive(int number)
{
if (number <= 0)
{
return;
}
Console.WriteLine(number);
}
Параметры и аргументы
Слова похожие, но означают разное, и в сообщениях компилятора они не взаимозаменяемы:
- параметр – то, что написано в объявлении:
int a; - аргумент – то, что передали при вызове:
3.
По умолчанию аргумент копируется. Для значимых типов это значит, что метод получает свою копию и оригинал изменить не может:
static void TryChange(int number)
{
number = 100;
}
int x = 5;
TryChange(x);
Console.WriteLine(x); // 5 – ничего не изменилось
Со ссылочными типами тоньше: копируется ссылка, но объект остаётся общим. Метод может изменить
содержимое массива, хотя саму переменную снаружи не тронет. Подробнее – в уроке про ref и out.
Короткая форма
Метод из одного return записывается стрелкой:
static int Square(int number) => number * number;
Это ровно то же самое, что и вариант с фигурными скобками. Форма удобна для однострочников; как только в теле появляется второе действие, возвращаются обычные скобки.
Где живут методы
В C# метод обязан лежать внутри класса. При инструкциях верхнего уровня класс создаёт компилятор, поэтому методы пишутся прямо в файле – но объявлять их нужно после основного кода:
Console.WriteLine(Sum(2, 3));
static int Sum(int a, int b) => a + b;
Порядок именно такой: сначала инструкции верхнего уровня, потом объявления. Наоборот компилятор не поймёт – он не сможет отделить точку входа от вспомогательного кода.
Хорошее имя метода – глагол или глагольная фраза: Calculate, GetUser, IsValid. Если имя получается существительным вроде Data, обычно это признак, что метод делает слишком много или что ему место в свойстве класса.
Сколько строк допустимо
Жёсткого правила нет, но есть надёжный признак: если, объясняя, что делает метод, вы говорите «и» больше одного раза – «читает файл, и разбирает строки, и считает сумму» – их должно быть три, а не один.
Метод, который делает одно дело, легко назвать. Метод, который делает три дела, называется
ProcessData – и это имя ничего не сообщает.