Ответ
Nullable-типы в C# — это структуры, которые позволяют переменным значимых типов (value types) представлять отсутствие значения, то есть иметь состояние null. Это решает проблему, когда int, bool, DateTime и другие структуры по умолчанию не могут быть null.
Синтаксис
- Полная форма:
Nullable<T>(например,Nullable<int>). - Сокращенная форма (синтаксический сахар):
T?(например,int?,bool?,DateTime?).
Основные свойства и методы
int? nullableNumber = null;
DateTime? nullableDate = DateTime.Now;
// 1. Проверка наличия значения
if (nullableNumber.HasValue) // или if (nullableNumber != null)
{
// 2. Получение значения (выбросит InvalidOperationException, если HasValue == false)
int actualNumber = nullableNumber.Value;
// Альтернатива: безопасное получение со значением по умолчанию
int safeNumber = nullableNumber.GetValueOrDefault(); // вернет 0, если null
int safeNumberWithDefault = nullableNumber.GetValueOrDefault(42); // вернет 42, если null
}
// 3. Приведение
int? a = 10;
int b = (int)a; // Явное приведение (опасно, если a == null)
// 4. Оператор объединения с null (null-coalescing operator)
int result = nullableNumber ?? 100; // Если nullableNumber != null, вернет его значение, иначе 100.
int result2 = nullableNumber ?? nullableDate?.Day ?? 0; // Цепочка операторов.
// 5. Условный null (null-conditional operator) с nullable
int? length = nullableString?.Length; // length будет int? (null если nullableString == null)
Практическое применение
- Работа с базами данных: Поля таблицы (например,
EndDate,MiddleName) часто могут бытьNULL. - Опциональные параметры методов: Вместо использования "магических" значений (например,
-1). - Состояния флагов:
bool?может означатьtrue/false/неизвестно.
Пример с Entity Framework/Dapper:
public class User
{
public int Id { get; set; }
public string FirstName { get; set; }
public string? MiddleName { get; set; } // Может быть null в БД
public DateTime BirthDate { get; set; }
public DateTime? LastLoginDate { get; set; } // Может быть null, если пользователь не логинился
}
Null Forgiving Operator (!):
Используется, чтобы сообщить компилятору, что выражение не будет null, даже если его статический анализ предполагает обратное. Используйте с осторожностью.
int? maybeNumber = GetPossibleNumber();
int definiteNumber = maybeNumber!.Value; // Мы "прощаем" возможный null, рискуя получить исключение.
Важно: Nullable reference types (NRT) (string? для ссылочных типов) — это отдельная функция C# 8+, которая помогает избежать NullReferenceException, но работает на уровне анализа компилятора, а не в runtime.