JavaRush /Курси /C# SELF /Робота з null: оператори ??, ?., ?, !, default

Робота з null: оператори ??, ?., ?, !, default

C# SELF
Рівень 14 , Лекція 3
Відкрита

1. Оператор об’єднання з null (??)

Ваші знання про nullable-типи не будуть повними без уміння писати лаконічні та безпечні конструкції. У C# для цього є два дуже корисні оператори: об’єднання з null (??) і null-умовний оператор (?.).

Оператор ?? дозволяє задати «значення за замовчуванням» для змінної, яка може бути null.

Уявіть, що у вас є імʼя користувача, яке може бути null. Якщо воно справді null, ви хочете показати «Гість». Приклад:

string userName = null;
string displayName = userName != null ? userName : "Гість";
Класична перевірка на null

Оператор ?? дозволяє записати це компактніше:

string userName = null;
string displayName = userName ?? "Гість";
Використання ?? для значення за замовчуванням

Як це працює:

  • Якщо вираз ліворуч не null, його значення повертається як результат.
  • Якщо ліворуч null, використовується значення праворуч.

Ще приклади:

int? age = null;
int displayAge = age ?? -1; // -1 — значення за замовчуванням
Console.WriteLine(displayAge); // Виведе -1

string input = null;
string name = input ?? "Гість";
Console.WriteLine($"Привіт, {name}!"); // Привіт, Гість!

Ланцюжки операторів

Можна вкладати ?? у ланцюжок:

string result = str1 ?? str2 ?? "За замовчуванням";
Ланцюжок операторів ??

Якщо str1 не null, використовується його значення. Інакше — str2. Якщо й він null, тоді — рядок «За замовчуванням».

2. null-умовний оператор (?.)

Ще одна типова ситуація — викликати метод або звертатися до властивості об’єкта лише тоді, коли сам об’єкт не null. Приклад:

User user = null;
string displayName = user != null ? user.Name : null;
Класична перевірка на null перед зверненням до властивості

Оператор ?. дозволяє записати це простіше:

User user = null;
string displayName = user?.Name;
null-умовний оператор ?.

Якщо об’єкт user дорівнює null, вираз не спричинить помилку, а просто поверне null.

Приклади:

User user = null;

// Без ?. — буде помилка
// Console.WriteLine(user.Name); // NullReferenceException

Console.WriteLine(user?.Name); // Безпечно — надрукує порожній рядок або нічого

Console.WriteLine(user?.GetProfileInfo()); // Аналогічно

User[] users = null;
int? count = users?.Length; // null, якщо users == null

Ланцюжки операторів

Можна будувати цілі «ланцюжки»:


string domain = company?.Director?.Email?.Split('@')?[1];
Ланцюжок ?. для безпечного доступу до вкладених властивостей

Якщо будь-яка частина шляху виявиться null, вираз поверне null, а не згенерує виняток.

Поєднання з ??

Оператори ?. і ?? чудово працюють разом:


string display = user?.Name ?? "Невідомо";
Безпечний вивід із підстановкою значення за замовчуванням

Якщо user або user.Name дорівнюють null, буде виведено «Невідомо».

3. Що таке ! і навіщо він потрібен

Оператор придушення попереджень про null

У сучасних версіях C# (якщо ввімкнено NRT) компілятор завбачливо попереджає, коли ви звертаєтеся до змінної, що може бути null. Але іноді ви впевнені, що все під контролем. Тоді використовується оператор придушення !.


string? possibleNull = GetUserNameMaybeNull();
Console.WriteLine(possibleNull.Length); // Попередження: можливий null

Console.WriteLine(possibleNull!.Length); // Компілятор мовчить, але якщо там null — буде виняток

Важливо: ! не захищає від помилок — він просто каже компілятору «повір мені». Якщо змінна справді дорівнює null, буде NullReferenceException.

Куди не варто його застосовувати

Не використовуйте ! навмання. Гарний стиль — мінімізувати його застосування. Краще перебудувати код так, щоб null був або неможливий, або явно оброблений.

4. default — як отримати «стандартне» значення типу

Іноді потрібно просто «скинути» змінну до початкового стану, особливо якщо не хочеться вручну писати 0, false чи null.

Для цього існує ключове слово default.

int a = default;            // a == 0
bool flag = default;        // flag == false
string s = default;         // s == null
double? d = default;        // d == null
Використання default для скидання змінних

У вашому мінізастосунку можна, наприклад, скинути імʼя чи вік:

userName = default; // null
userAge = default;  // null (якщо userAge — int?)

5. Відмінності та нюанси: ?, !, default

Навіть досвідчені розробники іноді губляться, коли бачать ?, ! і default поруч. Розберімося, хто є хто.

? — ви дозволяєте null

  • Для значущих типів: int? x — тепер x може бути null.
  • Для посилальних типів: string? s — ви явно вказуєте, що змінна може бути null (у режимі NRT).

! — ви запевняєте, що null не буде

  • user!.Name — ви обіцяєте компілятору, що user точно не null.
  • Працює тільки в режимі Nullable Reference Types.

default — ви просите значення «за замовчуванням»

  • int x = default; — x стане 0
  • string s = default; — s стане null

Порівняння:

Синтаксис Що це? Де працює? До чого тут null?
int?
Значущий тип, що допускає null Скрізь Можна присвоїти null
string?
Посилальний тип, що допускає null (NRT) У режимі NRT Можна присвоїти null
!
Оператор придушення попереджень про null У режимі NRT Придушує попередження
default
Значення за замовчуванням Скрізь Для посилальних — це null

6. Типові помилки під час використання ?, ! і default

Помилка № 1: вважають, що ! «лікує» null.
Насправді ! лише змушує компілятор не сваритися. Якщо значення таки виявиться null, програма впаде з NullReferenceException.

Помилка № 2: забувають перевіряти .HasValue перед використанням .Value.
Особливо це стосується int?, bool? та інших nullable-типів. Без такої перевірки можна отримати виняток InvalidOperationException.

Помилка № 3: застосовують default там, де потрібне «особливе» нульове значення.
Наприклад, 0 чи false можуть бути цілком допустимими значеннями, а не сигналами відсутності значення. Це може призвести до логічних помилок.

Помилка № 4: не використовують ? для посилальних типів у режимі NRT — або зловживають ним.
Хтось забуває про ?, і компілятор видає багато попереджень. А хтось, навпаки, всюди ставить ?, навіть там, де null ніколи не буває. І те, й інше знижує читабельність і надійність коду.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ