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

Метод: параметры и возврат

This lesson is not translated yet – the Russian original is below.

Метод – это кусок кода с именем. Пока программа умещается в двадцать строк, методы кажутся лишней церемонией. Как только строк становится двести, без них не разобраться.

Зачем они

Три причины, и только первая очевидна.

Не повторяться. Один и тот же расчёт в трёх местах – это три места, где придётся исправлять ошибку. Метод делает его одним.

Дать имя. 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 – и это имя ничего не сообщает.