$ sudo teach IT
Модуль 8 · Функции

Урок 8.1 — Методы и возврат значений

Функции в C#: DRY, return, void, static и область видимости.

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

❓

Зачем нужны методы?

Методы решают несколько проблем сразу:

🔄 DRY
Don't Repeat Yourself. Не повторяй один и тот же код 10 раз. Напиши метод один раз и вызывай его.
📦 Модульность
Код разбит на логические блоки, каждый отвечает за свою задачу. Легче читать, тестировать, отлаживать.
🔧 Удобство изменений
Нужно исправить логику? Меняешь в одном месте, а не в 20 копиях кода.
🧠 Абстракция
Можно использовать метод, не зная, как он устроен внутри. Как телевизор: ты жмёшь кнопку, а что там внутри — не важно.
C# · Без метода vs с методом
// ❌ Без метода — копируем код 3 раза
int a1 = 5 * 5;
Console.WriteLine(a1);

int a2 = 12 * 12;
Console.WriteLine(a2);

int a3 = 7 * 7;
Console.WriteLine(a3);

// ✅ С методом — один раз написали, 3 раза вызвали
static int Square(int x)
{
    return x * x;
}

Console.WriteLine(Square(5));   // 25
Console.WriteLine(Square(12));  // 144
Console.WriteLine(Square(7));   // 49
📝

Синтаксис метода

static тип Имя(параметры) { тело }

  • static — модификатор (пока используем, позже разберёмся)
  • тип — что метод возвращает: int, string, double... Если ничего не возвращает — void
  • Имя — глагол в PascalCase: CalculateSum, GetName, PrintMenu
  • параметры — входные данные, которые метод принимает (могут быть пустыми)
  • тело — код, который выполняется при вызове
C# · Первый метод
using System;

class Program
{
    // Метод, который приветствует пользователя
    static void SayHello()
    {
        Console.WriteLine("Привет, мир!");
    }

    // Метод, который возвращает сумму двух чисел
    static int Add(int a, int b)
    {
        return a + b;
    }

    static void Main()
    {
        SayHello();              // вызов void-метода
        int sum = Add(3, 5);     // вызов с возвратом значения
        Console.WriteLine(sum);  // 8
    }
}
↩️

return — возврат значения

Ключевое слово return решает две задачи:

  1. Возвращает результат вызывающему коду
  2. Завершает выполнение метода
C# · return
static int Max(int a, int b)
{
    if (a > b)
        return a;  // если a больше — выходим, возвращаем a
    return b;      // иначе возвращаем b
}

int result = Max(10, 7);  // result = 10
Console.WriteLine(result);

// return может быть выражением любой сложности:
static double CircleArea(double radius)
{
    return Math.PI * radius * radius;
}

Console.WriteLine(CircleArea(5));  // 78.53981633974483

⚠️ Важно: если метод объявлен с возвращаемым типом (не void), то return обязателен на всех путях выполнения. Компилятор проверит это. Если метод void, return использовать можно (просто return;), но не обязательно.

C# · Несколько return
// Один метод — несколько return
static string Grade(int score)
{
    if (score >= 90) return "Отлично";
    if (score >= 75) return "Хорошо";
    if (score >= 60) return "Удовлетворительно";
    if (score >= 40) return "Неудовлетворительно";
    return "Провал";  // дошли сюда — значит score < 40
}

Console.WriteLine(Grade(85));  // Хорошо
Console.WriteLine(Grade(95));  // Отлично
Console.WriteLine(Grade(30));  // Провал
🫥

Void-методы (без возврата)

Методы с типом void не возвращают никакого значения. Они выполняют действие: выводят текст, меняют состояние, записывают файл.

C# · Void-метод
static void PrintHeader(string title)
{
    Console.WriteLine("=".PadRight(40, '='));
    Console.WriteLine($"  {title}");
    Console.WriteLine("=".PadRight(40, '='));
}

static void PrintSeparator()
{
    Console.WriteLine("-".PadRight(40, '-'));
}

// Вызовы:
PrintHeader("Главное меню");
PrintSeparator();

// Void с return (досрочный выход):
static void PrintPositive(int number)
{
    if (number < 0)
        return;  // досрочно выходим, ничего не печатаем
    Console.WriteLine(number);
}

PrintPositive(5);   // 5
PrintPositive(-3);  // ничего не выведет
💡 return; в void-методе — это как «стоп, дальше не идём». Он прерывает выполнение метода. Полезно при проверке условий в начале метода (guard clause).
🔲

Локальные переменные и область видимости

Переменные, объявленные внутри метода, называются локальными. Они видны только в этом методе. Снаружи их нет:

C# · Область видимости
static void MethodA()
{
    int x = 10;          // x видна только внутри MethodA
    Console.WriteLine(x);
}

static void MethodB()
{
    // Console.WriteLine(x);  // ❌ Ошибка! x не видна здесь
    int y = 20;          // y видна только внутри MethodB
}

// Переменные в разных методах могут называться одинаково:
static void Foo()
{
    int value = 1;
    Console.WriteLine(value);
}

static void Bar()
{
    int value = 2;  // это другая переменная, не конфликтует
    Console.WriteLine(value);
}

// Внутри метода тоже есть вложенные области:
static void ScopeDemo()
{
    int outer = 100;

    if (outer > 0)
    {
        int inner = 200;      // видна только внутри if
        Console.WriteLine(outer + inner);  // 300
    }

    // Console.WriteLine(inner);  // ❌ Ошибка! inner не видна
    Console.WriteLine(outer);  // 100 — ок
}

✅ Правило: переменная живёт от места объявления до конца блока { }, в котором она объявлена. Это называется областью видимости (scope).

⚡

Модификатор static

Пока мы пишем всё в классе Program с методом Main. Метод Main — статический. Чтобы вызывать наши методы из Main, они тоже должны быть static (пока что). Позже, когда изучим классы и объекты, разберёмся с этим подробнее.

C# · static
class Program
{
    // Статический метод — можно вызвать без создания объекта
    static void Greet(string name)
    {
        Console.WriteLine($"Привет, {name}!");
    }

    // Main — точка входа, тоже static
    static void Main()
    {
        Greet("Анна");   // вызываем статический метод
        Greet("Борис");
    }
}

// Без static (метод экземпляра) — будет позже:
class Calculator
{
    public int Add(int a, int b)  // не static — нужен объект
    {
        return a + b;
    }
}

// var calc = new Calculator();
// calc.Add(3, 5);  // так вызываются нестатические методы
💡 static означает «принадлежит классу, а не объекту». Пока что просто добавляй static к своим методам, чтобы вызывать их из Main. В следующих модулях разберём разницу.
🧩

Практический пример: калькулятор через методы

Разобьём калькулятор на методы — каждый выполняет свою задачу:

C# · Калькулятор через методы
using System;

class Program
{
    static void PrintMenu()
    {
        Console.WriteLine("1. Сложить");
        Console.WriteLine("2. Вычесть");
        Console.WriteLine("3. Умножить");
        Console.WriteLine("4. Разделить");
        Console.WriteLine("5. Выйти");
    }

    static int ReadNumber(string prompt)
    {
        Console.Write(prompt);
        return int.Parse(Console.ReadLine());
    }

    static int Add(int a, int b) => a + b;
    static int Subtract(int a, int b) => a - b;
    static int Multiply(int a, int b) => a * b;
    static double Divide(int a, int b) => (double)a / b;

    static void Main()
    {
        while (true)
        {
            PrintMenu();
            int choice = ReadNumber("Выбери операцию: ");

            if (choice == 5) break;

            int x = ReadNumber("Первое число: ");
            int y = ReadNumber("Второе число: ");

            switch (choice)
            {
                case 1:
                    Console.WriteLine($"Результат: {Add(x, y)}");
                    break;
                case 2:
                    Console.WriteLine($"Результат: {Subtract(x, y)}");
                    break;
                case 3:
                    Console.WriteLine($"Результат: {Multiply(x, y)}");
                    break;
                case 4:
                    if (y == 0)
                        Console.WriteLine("На ноль делить нельзя!");
                    else
                        Console.WriteLine($"Результат: {Divide(x, y):F2}");
                    break;
            }
        }
    }
}
🧪

Мини-тест

Вопрос 1

Что будет в переменной result: static int Foo(int x) { return x * 2; } int r = Foo(5);?

Ответ: 10. Метод возвращает число, умноженное на 2.

Вопрос 2

Какой тип должен быть у метода, который не возвращает значение?

Ответ: void. Такой метод выполняет действие, но не возвращает результат.

Вопрос 3

Что выведет код: static int Test() { return 1; return 2; } Console.WriteLine(Test());?

Ответ: 1. После первого return метод завершается, второй return никогда не выполнится.

Вопрос 4

Где можно использовать переменную, объявленную внутри блока if { }?

Ответ: Только внутри этого блока if { }. После закрывающей скобки переменная не видна (область видимости).

🧩

Задание для тренировки

Напиши программу «Анализ чисел», которая:

  1. Содержит метод static int[] GenerateArray(int size, int min, int max) — создаёт массив случайных чисел
  2. Содержит метод static int Sum(int[] arr) — сумму элементов
  3. Содержит метод static double Average(int[] arr) — среднее
  4. Содержит метод static (int Min, int Max) MinMax(int[] arr) — минимум и максимум
  5. Содержит метод static void PrintStats(int[] arr) — выводит всё на экран
  6. В Main создай массив из 15 чисел (от -50 до 50) и выведи статистику
C# · Решение
using System;

class Program
{
    static int[] GenerateArray(int size, int min, int max)
    {
        int[] arr = new int[size];
        Random rnd = new Random();
        for (int i = 0; i < size; i++)
            arr[i] = rnd.Next(min, max + 1);
        return arr;
    }

    static int Sum(int[] arr)
    {
        int sum = 0;
        foreach (int n in arr) sum += n;
        return sum;
    }

    static double Average(int[] arr)
    {
        return (double)Sum(arr) / arr.Length;
    }

    static (int Min, int Max) MinMax(int[] arr)
    {
        int min = arr[0], max = arr[0];
        foreach (int n in arr)
        {
            if (n < min) min = n;
            if (n > max) max = n;
        }
        return (min, max);
    }

    static void PrintStats(int[] arr)
    {
        Console.WriteLine("Массив: " + string.Join(", ", arr));
        Console.WriteLine($"Сумма: {Sum(arr)}");
        Console.WriteLine($"Среднее: {Average(arr):F2}");
        var (min, max) = MinMax(arr);
        Console.WriteLine($"Мин: {min}, Макс: {max}");
        Console.WriteLine($"Длина: {arr.Length}");
    }

    static void Main()
    {
        int[] numbers = GenerateArray(15, -50, 50);
        PrintStats(numbers);
    }
}
📌

Что важно запомнить

1️⃣
Метод — это именованный блок кода. Синтаксис: static тип Имя(параметры) { тело }. Вызывается по имени: Имя(аргументы).
2️⃣
return — возвращает значение и завершает метод. Тип возврата обязан совпадать с объявленным. void — ничего не возвращает.
3️⃣
Локальные переменные живут только внутри метода. В разных методах могут быть переменные с одинаковыми именами — это разные переменные.
4️⃣
DRY (Don't Repeat Yourself) — главная причина использовать методы. Один раз написал, вызываешь когда нужно. Менять логику — в одном месте.
5️⃣
static — пока просто добавляй к методам, чтобы вызывать из Main. Имена методов в PascalCase: CalculateTotal, GetUserName.

Тест: 8.1: Методы и возврат значений

3 вопроса

Методы

Premium