В C# у нас есть две основные категории типов: типы значений и ссылочные типы. Типам значений никогда не может быть присвоено значение null. Это ключевое слово используется для представления пустой ссылки на объект. Если мы попытаемся присвоить null типу значения, мы получим ошибку компилятора.

Но что, если нам нужно представить значение, которое может быть, например, установлено как true, false или даже null? Мы можем воспользоваться преимуществом типа C#Nullable как для типов значение, так и, начиная с C# 8, для ссылочных типов, с некоторыми ключевыми отличиями (*).

Тип значения, допускающий значение NULL, имеет подчиненный тип и работает как своего рода контейнер вокруг него, добавляя null к своему базовому набору значений. Поэтому, если мы объявим логическую переменную, допускающую значение NULL, как в нашем предыдущем примере, ей может быть присвоено любое значение из набора {true, false, null}.

Чтобы определить тип переменной, допускающий значение NULL, нам нужно добавить вопросительный знак в качестве суффикса к подчиненному типу bool? b = null.

Добавление суффикса вопросительного знака к любому типу значения является сокращением для создания экземпляра универсальной структуры System.Nullable‹T›. Таким образом, мы могли бы также использовать более существенное, но совершенно эквивалентное объявление Nullable<bool> b = null.

Структура имеет два свойства: Value, которое возвращает значение подчиненного типа, если было присвоено допустимое значение, и HasValue, которое проверяет, имеет ли объект присвоенное значение. Мы можем выполнить такое же управление с помощью оператора !=. У него также есть удобный метод GetValueOrDefault(), который дает нам текущее значение или значение по умолчанию для подчиненного типа, если оно равно null.

Мы работаем с типами, которые могут быть null, поэтому наиболее частая операция, которую мы можем выполнить, — это проверить наличие null и соответственно присвоить или получить значение. Поскольку это так распространено, мы можем использовать очень лаконичное сокращение в качестве альтернативы классическому оператору if/else: оператор объединения с нулевым значением??.

В строке 10, если мы получаем нулевое значение из метода, мы присваиваем 0 переменной.

В дополнение к этому мы можем использовать оператор присваивания для объединения с нулевым значением??=, чтобы присвоить значение непосредственно переменной с нулевым значением highscore ??= 0.

В C# также есть условный оператор ?., похожий на оператор безопасной навигации в Angular, для проверки на значение null перед доступом к свойству объекта вместо использования условного оператора. Таким образом, если мы попытаемся получить доступ к некоторому свойству объекта, которое может быть нулевым, мы не получим ошибку времени выполнения, если объект окажется нулевым.

(*) Ссылочные типы, допускающие значение NULL, — это необязательная языковая функция, доступная в C# 8. Даже если они используют один и тот же суффикс вопросительного знака, это не сокращение для System.Nullable‹T›.