Fundamentals

Потік Керування

Вивчення умовних операторів, циклів, операторів переходу та зіставлення шаблонів у C# для управління виконанням програми

Потік Керування (Control Flow)

Вступ

Уявіть, що ви створюєте додаток для онлайн-магазину. Користувач додає товар до кошика, і програма має прийняти рішення: чи достатньо товару на складі? Якщо так — додати в кошик, якщо ні — показати повідомлення про відсутність. Далі програма має перевірити всі товари в кошику, обчислити загальну суму з урахуванням знижок та податків. Кожна з цих дій потребує потоку керування (control flow) — механізму, який визначає, які інструкції виконуються, в якому порядку та за яких умов.

Потік керування — це фундаментальна концепція програмування, яка дозволяє створювати динамічні та інтелектуальні програми. Без нього код виконувався б лише послідовно, рядок за рядком, що унеможливлювало б будь-яку складну логіку.

Потік керування (Control Flow) — це порядок, у якому виконуються окремі інструкції, вирази або виклики функцій у програмі. Він визначається за допомогою умовних операторів, циклів та операторів переходу. Докладніше у офіційній документації.

Що ви дізнаєтесь

У цьому розділі ви опануєте:

  • Умовні оператори для прийняття рішень (if, else, switch, тернарний оператор)
  • Цикли для повторення дій (for, foreach, while, do-while)
  • Оператори переходу для контролю виконання (break, continue, return)
  • Зіставлення шаблонів у switch виразах для елегантної обробки складних умов

Передумови

Перед вивченням цього розділу рекомендується ознайомитися з:


Умовні Оператори

Умовні оператори дозволяють програмі приймати рішення на основі певних умов. Це фундамент логіки будь-якої програми.

Оператор if

Найпростіший спосіб виконати код залежно від умови — це оператор if.

Синтаксис:

if (умова)
{
    // Код, що виконується, якщо умова істинна
}

Приклад:

int temperature = 25;

if (temperature > 20)
{
    Console.WriteLine("Сьогодні тепло!");
}
Завжди використовуйте фігурні дужки {} навіть для однорядкових блоків коду. Це покращує читабельність та запобігає помилкам при подальшому редагуванні коду.

Оператор if-else

Для обробки альтернативного сценарію використовується else:

int age = 16;

if (age >= 18)
{
    Console.WriteLine("Ви можете голосувати.");
}
else
{
    Console.WriteLine("Ви ще не досягли віку для голосування.");
}

Оператор else if

Для перевірки кількох умов послідовно:

int score = 85;

if (score >= 90)
{
    Console.WriteLine("Оцінка: Відмінно");
}
else if (score >= 75)
{
    Console.WriteLine("Оцінка: Добре");
}
else if (score >= 60)
{
    Console.WriteLine("Оцінка: Задовільно");
}
else
{
    Console.WriteLine("Оцінка: Незадовільно");
}

Вкладені умовні оператори

Умовні оператори можна вкладати один в одного:

int temperature = 22;
bool isRaining = false;

if (temperature > 20)
{
    if (isRaining)
    {
        Console.WriteLine("Тепло, але дощить. Візьміть парасольку!");
    }
    else
    {
        Console.WriteLine("Чудова погода для прогулянки!");
    }
}
else
{
    Console.WriteLine("Холодно. Одягніться тепліше.");
}
Надмірне вкладання умовних операторів (більше 2-3 рівнів) погіршує читабельність коду. Розгляньте можливість рефакторингу через раннє повернення (early return) або винесення логіки в окремі методи.

Тернарний Оператор

Тернарний оператор ?: — це скорочена форма if-else, яка повертає значення:

Синтаксис:

умова ? значення_якщо_істина : значення_якщо_хиба

Приклад:

int age = 20;
string status = age >= 18 ? "Дорослий" : "Неповнолітній";
Console.WriteLine(status); // Виведе: Дорослий
int number = 42;
string result;

if (number % 2 == 0)
{
    result = "Парне";
}
else
{
    result = "Непарне";
}
Використовуйте тернарний оператор для простих умов, які повертають значення. Для складної логіки краще використовувати звичайний if-else для покращення читабельності.

Оператор switch

Оператор switch використовується для багатоваріантного вибору на основі значення виразу.

Синтаксис:

switch (вираз)
{
    case значення1:
        // Код для значення1
        break;
    case значення2:
        // Код для значення2
        break;
    default:
        // Код за замовчуванням
        break;
}

Приклад:

int dayOfWeek = 3;

switch (dayOfWeek)
{
    case 1:
        Console.WriteLine("Понеділок");
        break;
    case 2:
        Console.WriteLine("Вівторок");
        break;
    case 3:
        Console.WriteLine("Середа");
        break;
    case 4:
        Console.WriteLine("Четвер");
        break;
    case 5:
        Console.WriteLine("П'ятниця");
        break;
    case 6:
        Console.WriteLine("Субота");
        break;
    case 7:
        Console.WriteLine("Неділя");
        break;
    default:
        Console.WriteLine("Некоректний день тижня");
        break;
}

Множинні мітки case

Можна об'єднувати кілька міток case для виконання одного блоку коду:

int dayOfWeek = 6;

switch (dayOfWeek)
{
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
        Console.WriteLine("Робочий день");
        break;
    case 6:
    case 7:
        Console.WriteLine("Вихідний");
        break;
    default:
        Console.WriteLine("Некоректний день");
        break;
}
У C# немає "провалювання" (fall-through) між блоками case, як у деяких інших мовах. Кожен case має закінчуватися оператором break, return, goto або throw.

Порівняння умовних конструкцій

КонструкціяКоли використовуватиПеревагиНедоліки
if-elseУмови на основі булевих виразів, складна логікаУніверсальність, зрозумілістьБагато коду для простих випадків
Тернарний операторПрості умови з поверненням значенняКомпактністьПогана читабельність при вкладанні
switchПеревірка одного виразу на множину значеньЧитабельність для багатьох варіантівОбмежений тип виразу (до C# 7)
switch виразЯк switch, але з поверненням значенняКомпактність, pattern matchingПотребує C# 8.0+

Цикли

Цикли дозволяють повторювати блок коду кілька разів. Це критично важливо для обробки колекцій, повторення дій та реалізації алгоритмів.

Цикл for

Цикл for використовується, коли кількість ітерацій відома заздалегідь.

Синтаксис:

for (ініціалізація; умова; ітератор)
{
    // Код, що повторюється
}

Компоненти:

  • Ініціалізація: виконується один раз перед початком циклу
  • Умова: перевіряється перед кожною ітерацією
  • Ітератор: виконується після кожної ітерації

Приклад:

for (int i = 0; i < 5; i++)
{
    Console.WriteLine($"Ітерація: {i}");
}
// Виведе:
// Ітерація: 0
// Ітерація: 1
// Ітерація: 2
// Ітерація: 3
// Ітерація: 4

Множинні вирази в for

Можна використовувати кілька змінних:

for (int i = 0, j = 10; i < j; i++, j--)
{
    Console.WriteLine($"i = {i}, j = {j}");
}
Цикл for ідеально підходить для роботи з масивами, коли потрібен доступ до індексу елемента.

Цикл foreach

Цикл foreach використовується для ітерації по колекціях без необхідності маніпулювати індексом.

Синтаксис:

foreach (тип змінна in колекція)
{
    // Код, що використовує змінну
}

Приклад:

string[] fruits = { "Яблуко", "Банан", "Апельсин", "Груша" };

foreach (string fruit in fruits)
{
    Console.WriteLine($"Фрукт: {fruit}");
}

Неявна типізація з var

Компілятор може автоматично визначити тип:

var numbers = new[] { 1, 2, 3, 4, 5 };

foreach (var number in numbers)
{
    Console.WriteLine(number * 2);
}
Цикл foreach працює з будь-яким типом, що реалізує інтерфейс IEnumerable або IEnumerable<T>. Елементи колекції доступні лише для читання всередині циклу.
int[] numbers = { 10, 20, 30, 40, 50 };

for (int i = 0; i < numbers.Length; i++)
{
    Console.WriteLine($"Індекс {i}: {numbers[i]}");
}

Цикл while

Цикл while виконується доки умова істинна. Він використовується, коли кількість ітерацій невідома наперед.

Синтаксис:

while (умова)
{
    // Код, що повторюється
}

Приклад:

int count = 0;

while (count < 5)
{
    Console.WriteLine($"Лічильник: {count}");
    count++;
}
Остерігайтесь нескінченних циклів! Переконайтеся, що умова циклу while колись стане хибною, інакше програма зависне.
// НЕ РОБІТЬ ТАК!
while (true)
{
    // Цей код виконуватиметься вічно
}

Цикл do-while

Цикл do-while схожий на while, але гарантує виконання тіла циклу принаймні один раз, оскільки умова перевіряється після виконання блоку коду.

Синтаксис:

do
{
    // Код, що повторюється
} while (умова);

Приклад:

int userInput;

do
{
    Console.Write("Введіть число більше 0: ");
    userInput = int.Parse(Console.ReadLine());
} while (userInput <= 0);

Console.WriteLine($"Ви ввели: {userInput}");
int count = 10;

while (count < 5)
{
    Console.WriteLine(count);
    count++;
}
// Код не виконається жодного разу

Порівняння типів циклів

Тип циклуКоли використовуватиОсобливості
forКількість ітерацій відома, потрібен індексКомпактний синтаксис, ініціалізація + умова + ітератор
foreachІтерація по колекції без індексуНайпростіший синтаксис, лише для читання
whileКількість ітерацій невідома, перевірка в початкуУмова перевіряється перед виконанням
do-whileТе саме що while, але потрібне мінімум 1 виконанняУмова перевіряється після виконання

Візуалізація виконання циклів

Loading diagram...
flowchart TD
    Start([Start]) --> Input[/Input: age/]
    Input --> Check{age >= 18?}
    Check -->|Yes| Adult["You are an adult"]
    Check -->|No| Minor["You are a minor"]
    Adult --> End([End])
    Minor --> End

    style Start fill:#3b82f6,stroke:#1d4ed8,color:#ffffff
    style Input fill:#64748b,stroke:#334155,color:#ffffff
    style Check fill:#f59e0b,stroke:#b45309,color:#ffffff
    style Adult fill:#3b82f6,stroke:#1d4ed8,color:#ffffff
    style Minor fill:#3b82f6,stroke:#1d4ed8,color:#ffffff
    style End fill:#64748b,stroke:#334155,color:#ffffff

Оператори Переходу

Оператори переходу (jump statements) дозволяють змінювати нормальний потік виконання програми. Вони можуть переривати цикли, пропускати ітерації або виходити з методів.

Оператор break

Оператор break припиняє виконання найближчого циклу або оператора switch.

Використання в циклі:

for (int i = 0; i < 10; i++)
{
    if (i == 5)
    {
        break; // Вихід з циклу при i = 5
    }
    Console.WriteLine(i);
}
// Виведе: 0 1 2 3 4

Використання у вкладених циклах:

for (int i = 0; i < 3; i++)
{
    for (int j = 0; j < 3; j++)
    {
        if (j == 1)
        {
            break; // Виходить лише з внутрішнього циклу
        }
        Console.WriteLine($"i={i}, j={j}");
    }
}
break припиняє лише найближчий цикл або switch. Для виходу з кількох вкладених циклів використовуйте прапорець (flag) або винесіть код у метод з return.

Оператор continue

Оператор continue пропускає решту коду в поточній ітерації циклу та переходить до наступної ітерації.

for (int i = 0; i < 10; i++)
{
    if (i % 2 == 0)
    {
        continue; // Пропустити парні числа
    }
    Console.WriteLine(i);
}
// Виведе: 1 3 5 7 9

Практичний приклад:

string[] files = { "document.txt", "image.png", "data.csv", "photo.jpg", "report.txt" };

foreach (string file in files)
{
    if (!file.EndsWith(".txt"))
    {
        continue; // Пропустити файли, що не є текстовими
    }
    Console.WriteLine($"Обробка текстового файлу: {file}");
}
// Виведе:
// Обробка текстового файлу: document.txt
// Обробка текстового файлу: report.txt
Використовуйте continue для покращення читабельності коду, щоб уникнути глибокого вкладання умовних операторів у циклах.

Оператор return

Оператор return припиняє виконання методу та повертає керування викликаючому коду. Він може повертати значення або бути порожнім (для методів типу void).

Повернення значення:

int Add(int a, int b)
{
    return a + b; // Повертає суму
}

int result = Add(5, 3); // result = 8

Використання для раннього виходу:

void ProcessOrder(Order order)
{
    if (order == null)
    {
        Console.WriteLine("Помилка: замовлення відсутнє");
        return; // Ранній вихід з методу
    }

    if (order.Items.Count == 0)
    {
        Console.WriteLine("Помилка: замовлення порожнє");
        return; // Ранній вихід
    }

    // Обробка замовлення
    Console.WriteLine($"Обробка замовлення {order.Id}");
}
Ранній вихід (Early Return) покращує читабельність, дозволяючи уникнути глибокого вкладання умовних операторів. Спочатку перевіряйте помилкові умови та виходьте, а потім обробляйте основну логіку.

Порівняння операторів переходу

break

Повністю виходить з циклу або switch. Виконання продовжується з наступного оператора після циклу.

for (int i = 0; i < 10; i++)
{
    if (i == 5) break;
    Console.Write(i + " ");
}
// Виведе: 0 1 2 3 4

continue

Пропускає решту коду в поточній ітерації, але цикл продовжується. Переходить безпосередньо до наступної ітерації.

for (int i = 0; i < 10; i++)
{
    if (i == 5) continue;
    Console.Write(i + " ");
}
// Виведе: 0 1 2 3 4 6 7 8 9

return

Виходить з усього методу, незалежно від циклів. Може повертати значення.

int FindFirst(int[] arr, int target)
{
    for (int i = 0; i < arr.Length; i++)
    {
        if (arr[i] == target)
        {
            return i; // Повертає індекс
        }
    }
    return -1; // Не знайдено
}

Зіставлення Шаблонів у Switch Виразах

Починаючи з C# 8.0, мова отримала потужний функціонал зіставлення шаблонів (pattern matching), який революціонізував роботу з умовною логікою. Switch вирази (switch expressions) — це сучасна альтернатива традиційним операторам switch, яка є більш виразною та компактною.

Еволюція: від оператора до виразу

string GetSeasonName(int month)
{
    string season;

    switch (month)
    {
        case 12:
        case 1:
        case 2:
            season = "Зима";
            break;
        case 3:
        case 4:
        case 5:
            season = "Весна";
            break;
        case 6:
        case 7:
        case 8:
            season = "Літо";
            break;
        case 9:
        case 10:
        case 11:
            season = "Осінь";
            break;
        default:
            season = "Невідомо";
            break;
    }

    return season;
}
Switch вираз — це компактна форма оператора switch, яка повертає значення. Основні відмінності:
  • Використовує => замість : та break
  • Значення записується справа від =>
  • Це вираз, а не оператор, тому повертає значення
  • Використовує _ (discard) замість default

Основні типи шаблонів

Константні шаблони (Constant Patterns)

Перевірка на точну відповідність значенню:

string GetDayType(int day) => day switch
{
    6 => "Субота",
    7 => "Неділя",
    _ => "Робочий день"
};

Реляційні шаблони (Relational Patterns)

Використання операторів порівняння <, >, <=, >=:

string GetWaterState(int temperature) => temperature switch
{
    < 0 => "Лід",
    0 => "Точка замерзання",
    > 0 and < 100 => "Рідина",
    100 => "Точка кипіння",
    > 100 => "Пара",
    _ => "Невідомий стан"
};

Логічні шаблони (Logical Patterns)

Комбінування шаблонів за допомогою and, or, not:

bool IsWeekday(int day) => day switch
{
    >= 1 and <= 5 => true,
    6 or 7 => false,
    _ => throw new ArgumentException("Некоректний день")
};

string ClassifyAge(int age) => age switch
{
    < 0 => "Некоректний вік",
    >= 0 and < 13 => "Дитина",
    >= 13 and < 18 => "Підліток",
    >= 18 and < 65 => "Дорослий",
    >= 65 => "Пенсіонер"
};

Шаблони властивостей (Property Patterns)

Перевірка властивостей об'єктів:

public record Person(string Name, int Age);

string GetCategory(Person person) => person switch
{
    { Age: < 18 } => "Неповнолітній",
    { Age: >= 18, Name: "Admin" } => "Адміністратор",
    { Age: >= 18 } => "Дорослий користувач",
    _ => "Невідомо"
};

Позиційні шаблони (Positional Patterns)

Використання деконструкції для перевірки кортежів або типів з деконструктором:

public record Point(int X, int Y);

string GetQuadrant(Point point) => point switch
{
    (0, 0) => "Початок координат",
    (> 0, > 0) => "Перший квадрант",
    (< 0, > 0) => "Другий квадрант",
    (< 0, < 0) => "Третій квадрант",
    (> 0, < 0) => "Четвертий квадрант",
    (_, 0) => "На осі X",
    (0, _) => "На осі Y"
};

Discard Pattern

Використання _ для ігнорування значень:

string GetInfo((string name, int age, string city) person) => person switch
{
    ("John", _, _) => "Це John, незалежно від віку та міста",
    (_, > 65, _) => "Пенсіонер",
    (_, _, "Kyiv") => "Житель Києва",
    _ => "Інший користувач"
};

Застереження (Case Guards) з when

Додаткові умови для більш точного зіставлення:

decimal CalculateDiscount(int age, bool isMember) => (age, isMember) switch
{
    ( < 18, _) => 0.20m, // 20% для дітей
    ( >= 65, _) => 0.15m, // 15% для пенсіонерів
    (_, true) when age >= 18 && age < 65 => 0.10m, // 10% для членів
    _ => 0m // Без знижки
};

Складніший приклад з when:

public record Order(int ItemCount, decimal TotalPrice, bool IsPriority);

string GetShippingMethod(Order order) => order switch
{
    { IsPriority: true } => "Експрес доставка",
    { ItemCount: > 10, TotalPrice: > 1000 } => "Вантажна доставка",
    { TotalPrice: > 500 } when order.ItemCount <= 5 => "Стандартна доставка з упаковкою",
    { ItemCount: <= 3 } => "Кур'єрська служба",
    _ => "Звичайна пошта"
};

Вичерпність (Exhaustiveness Checking)

Компілятор C# перевіряє, чи охоплюють шаблони всі можливі значення. Якщо ні, виникне попередження:

enum TrafficLight { Red, Yellow, Green }

// Попередження CS8509: Не всі значення охоплені
string GetAction(TrafficLight light) => light switch
{
    TrafficLight.Red => "Стоп",
    TrafficLight.Green => "Рух"
    // Відсутній Yellow!
};

// Правильна версія:
string GetActionCorrect(TrafficLight light) => light switch
{
    TrafficLight.Red => "Стоп",
    TrafficLight.Yellow => "Підготуватися",
    TrafficLight.Green => "Рух",
    _ => throw new ArgumentException("Невідомий сигнал")
};

Порівняння: традиційний switch vs switch вираз

АспектТрадиційний switchSwitch вираз
СинтаксисОператор з case, :, breakВираз з =>
Повернення значенняПотрібна окрема зміннаПряме повернення
КомпактністьБагатослівнийЛаконічний
Pattern matchingОбмежений (C# 7+)Повна підтримка
Перевірка вичерпностіНіТак (попередження)
Версія C#Всі версіїC# 8.0+

Практичний приклад: обробка HTTP статусів

public record HttpResponse(int StatusCode, string Body);

string HandleResponse(HttpResponse response) => response switch
{
    { StatusCode: 200, Body: not null } => $"Успіх: {response.Body}",
    { StatusCode: 200, Body: null } => "Успіх, але немає даних",
    { StatusCode: >= 200 and < 300 } => "Успішна відповідь",
    { StatusCode: 400 } => "Поганий запит",
    { StatusCode: 401 } => "Не авторизовано",
    { StatusCode: 404 } => "Не знайдено",
    { StatusCode: >= 400 and < 500 } => "Помилка клієнта",
    { StatusCode: >= 500 } => "Помилка сервера",
    _ => "Невідомий статус"
};
Switch вирази особливо корисні для створення чистого, декларативного коду. Вони ідеально підходять для:
  • Маппінгу значень (value mapping)
  • Класифікації даних
  • Обробки складних умов на основі множини властивостей
  • Редюсерів у state management
Loading diagram...
flowchart TD
    Start([Вхідне значення]) --> Switch{Switch вираз}
    Switch -->|Pattern 1 збігся| Result1[=> Результат 1]
    Switch -->|Pattern 2 збігся| Result2[=> Результат 2]
    Switch -->|Pattern 3 збігся| Result3[=> Результат 3]
    Switch -->|Pattern N збігся| ResultN[=> Результат N]
    Switch -->|Жоден не збігся| Discard[=> _ discard/default]

    Result1 --> End([Повернення значення])
    Result2 --> End
    Result3 --> End
    ResultN --> End
    Discard --> End

Найкращі Практики та Поширені Помилки

Найкращі практики

1. Уникайте глибокого вкладанняЗамість глибоко вкладених умов використовуйте ранній вихід:
void ProcessUser(User user)
{
    if (user != null)
    {
        if (user.IsActive)
        {
            if (user.HasPermission)
            {
                // Основна логіка
            }
        }
    }
}
2. Використовуйте правильний тип циклу
  • for — коли потрібен індекс або конкретна кількість ітерацій
  • foreach — для простої ітерації по колекції
  • while — коли кількість ітерацій невідома
  • do-while — коли потрібне мінімум одне виконання
3. Віддавайте перевагу switch виразамДля сучасного C# 8.0+ коду використовуйте switch вирази замість традиційних операторів switch, коли це доцільно.
4. Використовуйте осмислені імена змінних у циклах
foreach (var x in items)
{
    // Що таке x?
}

Поширені помилки

Нескінченні цикли
// Помилка: лічильник не змінюється
int i = 0;
while (i < 10)
{
    Console.WriteLine(i);
    // Забули i++
}
Вирішення: Завжди перевіряйте, що умова циклу колись стане хибною.
Зміна колекції під час ітерації
var numbers = new List<int> { 1, 2, 3, 4, 5 };

// Помилка: зміна списку під час ітерації
foreach (var num in numbers)
{
    if (num % 2 == 0)
    {
        numbers.Remove(num); // InvalidOperationException!
    }
}
Вирішення: Використовуйте for в зворотному порядку або створіть нову колекцію.
// Правильно: ітерація у зворотному порядку
for (int i = numbers.Count - 1; i >= 0; i--)
{
    if (numbers[i] % 2 == 0)
    {
        numbers.RemoveAt(i);
    }
}
Відсутність break у switch
// Помилка компіляції в C#
switch (value)
{
    case 1:
        Console.WriteLine("One");
        // Забули break - помилка компіляції!
    case 2:
        Console.WriteLine("Two");
        break;
}
Вирішення: Завжди додавайте break, return або goto в кінці кожного case.
Неправильне використання continue та break
// Помилка: плутанина між continue та break
for (int i = 0; i < 10; i++)
{
    if (i == 5)
    {
        continue; // Пропускає лише 5
    }
    Console.WriteLine(i);
}
// Очікували вихід на 5, але отримали пропуск
Розуміння:
  • break — виходить з циклу
  • continue — пропускає поточну ітерацію

Troubleshooting (Усунення помилок)

Проблема 1: Condition is always true/false

Симптом: Попередження компілятора про завжди істинну або хибну умову.

int x = 5;
if (x = 5) // Помилка: присвоєння замість порівняння
{
    // ...
}

Вирішення:

int x = 5;
if (x == 5) // Правильно: оператор порівняння
{
    // ...
}

Проблема 2: Unreachable code detected

Симптом: Код після return, break або безумовного переходу ніколи не виконується.

int GetValue()
{
    return 42;
    Console.WriteLine("Це ніколи не виконається"); // Попередження
}

Вирішення: Видаліть недосяжний код або перегляньте логіку.

Проблема 3: Не всі шляхи повертають значення

Симптом: Компілятор повідомляє, що метод не завжди повертає значення.

int GetSign(int number)
{
    if (number > 0)
    {
        return 1;
    }
    else if (number < 0)
    {
        return -1;
    }
    // Що якщо number == 0?
}

Вирішення:

int GetSign(int number)
{
    if (number > 0) return 1;
    if (number < 0) return -1;
    return 0; // Обробка всіх випадків
}

Проблема 4: Off-by-one error у циклах

Симптом: Цикл виконується на одну ітерацію більше або менше, ніж очікувалось.

int[] arr = { 1, 2, 3, 4, 5 };

// Помилка: IndexOutOfRangeException
for (int i = 0; i <= arr.Length; i++) // Повинно бути <, а не <=
{
    Console.WriteLine(arr[i]);
}

Вирішення:

for (int i = 0; i < arr.Length; i++) // Правильно
{
    Console.WriteLine(arr[i]);
}

Практичні Завдання

Рівень 1: Базовий

Завдання 1.1: Парність числа

Напишіть програму, яка запитує у користувача ціле число та визначає, чи є воно парним або непарним, використовуючи оператор if-else.

Завдання 1.2: Сума чисел від 1 до N

Напишіть програму, яка обчислює суму всіх цілих чисел від 1 до N (включно) за допомогою циклу for.

Завдання 1.3: Виведення масиву

Створіть масив з 5 елементів та виведіть всі його елементи за допомогою циклу foreach.

Рівень 2: Середній

Завдання 2.1: Калькулятор з switch

Створіть простий калькулятор, який приймає два числа та оператор (+, -, *, /) і виконує відповідну операцію, використовуючи switch вираз.

Завдання 2.2: Таблиця множення

Напишіть програму, яка виводить таблицю множення для числа від 1 до 10, використовуючи вкладені цикли for.

Завдання 2.3: Пошук простих чисел

Напишіть програму, яка знаходить всі прості числа від 2 до N. Використовуйте оператори continue або break для оптимізації.

Рівень 3: Просунутий

Завдання 3.1: Pattern Matching для класифікації фігур

Створіть ієрархію класів для геометричних фігур (коло, прямокутник, трикутник) та напишіть метод, який використовує pattern matching для обчислення площі.

Завдання 3.2: Оптимізація пошуку в масиві

Напишіть метод бінарного пошуку в відсортованому масиві. Використовуйте цикл while та оператори переходу для ефективного пошуку.

Завдання 3.3: Складний switch вираз для обробки HTTP запитів

Створіть систему обробки HTTP запитів з використанням pattern matching для маршрутизації та обробки різних типів запитів.


Резюме

У цьому розділі ви вивчили потік керування (control flow) — фундаментальні механізми, які дозволяють програмам приймати рішення та повторювати дії:

Умовні оператори:

  • if, else, else if для базових умовних розгалужень
  • Тернарний оператор ? : для компактних умовних виразів
  • Оператор switch для множинного вибору
  • Сучасні switch вирази з pattern matching (C# 8.0+)

Цикли:

  • for — для фіксованої кількості ітерацій з доступом до індексу
  • foreach — для зручної ітерації по колекціях
  • while — для циклів з попередньою перевіркою умови
  • do-while — для циклів з гарантованим першим виконанням

Оператори переходу:

  • break — вихід з циклу або switch
  • continue — пропуск поточної ітерації циклу
  • return — вихід з методу з можливим поверненням значення

Pattern Matching:

  • Константні, реляційні, логічні шаблони
  • Шаблони властивостей та позиційні шаблони
  • Case guards з when для додаткових умов
  • Перевірка вичерпності компілятором

Опанування потоку керування — це ключ до написання ефективної та елегантної логіки програми. Практикуйте різні підходи, обирайте найбільш читабельні рішення та використовуйте сучасні можливості C# для створення чистого коду!