OOP Course
Сьогодні

Підрозділ 8.2

Визначення інкременту та декременту

Розглядає перевантаження інкременту, декременту, операторів true і false та використання об'єкта як умови.

8.2. Визначення інкременту та декременту

Оператори ++ і -- — унарні, тобто вони приймають один операнд і повертають змінений стан. Для користувацьких типів їх можна перевантажити так само, як і будь-який інший оператор. Однак у них є важлива особливість, яку необхідно враховувати при визначенні.

Правило незмінності параметрів

Коли ми визначаємо оператор ++ або --, параметр методу представляє поточний об'єкт. Інтуїтивно здається, що потрібно просто змінити значення прямо у методі:

// НЕПРАВИЛЬНО — мутуємо параметр
public static BodyTemperature operator ++(BodyTemperature t)
{
    t.Celsius += 0.1; // не можна: Celsius — readonly
    return t;
}

Це неправильний підхід з двох причин. По-перше, якщо властивість доступна лише для читання (що є стандартом для immutable-типів), такий код не скомпілюється. По-друге, і це головне: оператор не повинен мутувати свої параметри. Параметри — це входи, а не виходи. Правильне визначення — повернути новий об'єкт з оновленим значенням:

// ПРАВИЛЬНО — повертаємо новий об'єкт
public static BodyTemperature operator ++(BodyTemperature t)
{
    return new BodyTemperature(t.Celsius + 0.1);
}

Цей підхід відомий як «immutable update pattern»: замість зміни існуючого об'єкта ми створюємо новий із потрібним значенням. Він запобігає побічним ефектам і є стандартом при визначенні операторів у C#.

Синтаксис оператора інкременту та декременту

Оскільки ++ і -- — унарні оператори, вони приймають один параметр. Одне визначення охоплює і префіксну (++t), і постфіксну (t++) форму — компілятор сам реалізує різницю:

Math.Round(..., 1) тут необхідний через особливості арифметики чисел із плаваючою крапкою: 36.6 + 0.1 без округлення може дати 36.699999... замість 36.7.

Префіксна та постфіксна форми: як компілятор розрізняє їх

Хоча ми визначаємо один метод, поведінка t++ і ++t — різна. Різниця не в тому, як змінюється об'єкт, а в тому, яке значення повертається як результат виразу. Компілятор реалізує це самостійно на основі одного нашого визначення.

Постфіксний і префіксний ++: одне визначення, різна поведінка

Побачимо різницю в дії:

При постфіксному t1++ компілятор виконує три дії: зберігає поточний об'єкт у тимчасову змінну, замінює t1 результатом operator++(t1), а як результат виразу повертає тимчасову (стару) копію. При префіксному ++t3 — викликає operator++(t3), присвоює результат t3 і повертає його ж.

Ця різниця важлива лише тоді, коли результат виразу використовується: t2 = t1++ та t2 = ++t1 поводяться по-різному. Якщо ж ми пишемо просто t++; або ++t; в окремому рядку — різниці немає.

Оператори true та false

Окрема пара унарних операторів — true і false. Вони визначаються, коли ми хочемо використовувати об'єкт нашого класу безпосередньо як умову в if, while або тернарному операторі — без явного виклику методу чи порівняння з bool.

У клінічній системі природним кандидатом є клас MedicalDevice. Пристрій може бути активним або офлайн, і зручно писати if (device) замість if (device.IsOnline):

Оператори true і false завжди визначаються парою — компілятор вимагає наявності обох. Оператор ! не є обов'язковим, але без нього конструкція if (!device) не компілюється. Семантично !device збігається з оператором false — обидва перевіряють, що пристрій «не true».

Повний приклад: температурний моніторинг

Об'єднаємо ++, -- і true/false у реалістичному клінічному сценарії — автоматичному відстеженні температури пацієнта після лікування:

У цьому прикладі if (!temp) перевіряє аномальний стан, а if (temp) у циклі фіксує повернення до норми. Код читається природно і не вимагає явного звертання до IsNormal або IsFever у кожній умові.

Розроблено Tomka Yurii · © 2026 ·