Что такое nullable тип в C# и как использовать оператор null-coalescing ???
Nullable<T> (запись T?) позволяет значимому типу хранить null. Оператор ?? возвращает левый операнд, если он не null, иначе — правый; ??= присваивает правый операнд только при null.
Nullable-типы в C#
Nullable-тип позволяет значимому типу (int, bool, DateTime и т.д.) принимать значение null. Реализуется через структуру Nullable<T>, которая имеет сокращённую запись T?. Под капотом хранятся два поля: HasValue (bool) и Value (T).
int? age = null; // Nullable<int>
bool? flag = true;
if (age.HasValue)
Console.WriteLine(age.Value);
else
Console.WriteLine("age не задан");
Оператор null-coalescing ??
Оператор ?? возвращает левый операнд, если он не равен null, иначе — правый. Это удобная альтернатива тернарному оператору для проверки на null.
int? score = null;
int result = score ?? 0; // result = 0
string? name = GetName(); // может вернуть null
string display = name ?? "Аноним";
Оператор ??= (null-coalescing assignment, C# 8+)
Присваивает правый операнд переменной, только если она равна null.
List<string>? items = null;
items ??= new List<string>();
items.Add("первый");
Цепочки ??
Операторы можно цеплять: вычисляется первый не-null результат слева направо.
string? a = null;
string? b = null;
string c = "default";
string result = a ?? b ?? c; // "default"
Оператор ?. (null-conditional) в связке с ??
Оператор ?. возвращает null вместо NullReferenceException, и его часто объединяют с ?? для безопасного обращения к членам объекта.
string? GetCity(User? user)
=> user?.Address?.City ?? "Неизвестно";
Получение значения с дефолтом
У Nullable<T> есть метод GetValueOrDefault(defaultValue) — альтернатива ?? для простых случаев.
int? x = null;
int val = x.GetValueOrDefault(-1); // -1
// Эквивалентно: x ?? -1
Подводные камни
- Обращение к
Valueбез проверкиHasValueбросаетInvalidOperationException, а неNullReferenceException— путает при отладке. Nullable<T>— структура, но boxing превращает её вnullили упакованныйT, что теряет информацию о типе при рефлексии.- Правый операнд
??вычисляется лениво только в случае, когда левая частьnull— но если это метод с побочными эффектами, поведение может удивить. ??=работает только дляnull-проверки; проверять другие falsy-значения (0, пустую строку) им нельзя.- Смешение
int?иintв арифметических выражениях: результат имеет типint?, и это иногда приводит к неожиданномуnullна выходе. - В LINQ-запросах EF Core nullable-столбцы могут не совпадать с C# nullable-типами, если миграции не настроены под
IsRequired()/IsNullable(). - Начиная с C# 8 есть ещё nullable reference types (
string?) — они не то же самое, чтоNullable<string>, и смешивать их семантику опасно.
Common mistakes
- Путать nullable-типы и оператор null-coalescing с похожим механизмом из другой версии или платформы.
- Игнорировать runtime-границы C#: lifecycle, DI scope, SQL translation, UI thread или platform API.
- Не обсуждать null/empty/error cases и поведение под нагрузкой.
What the interviewer is testing
- Кандидат объясняет nullable-типы и оператор null-coalescing на конкретном примере, а не только определением.
- Указывает последствия для производительности, тестируемости и поддержки.
- Различает документированное поведение текущего стека и устаревшие практики.