Справочник по C#. Типы значений, допускающие значение NULL
Тип значения, допускающий значение NULL , представляет все значения базового типа значения и дополнительное значение null . Например, можно присвоить переменной bool? любое из следующих трех значений: true , false или null . Базовый тип значения T не может соответствовать типу значения, допускающему значение NULL.
В C# 8.0 появилась возможность использования ссылочных типов, допускающих значение NULL. Дополнительные сведения см. в статье Ссылочные типы, допускающие значение NULL. Типы значений, допускающие значение NULL, доступны начиная с C# 2.
Типы, допускающие значение NULL, представляют собой экземпляры универсальной структуры System.Nullable<T>. Вы можете ссылаться на тип значения, допускающий значение NULL, с базовым типом T в любой из следующих взаимозаменяемых форм: Nullable<T> или T? .
Тип значения, допускающий значение NULL, следует использовать, когда нужно представить неопределенное значение его базового типа. Например, логическая переменная (или bool ) может иметь только значения true или false . Однако в некоторых приложениях значение переменной может быть неопределенным или отсутствовать. Например, поле базы данных может содержать значение true или false либо вообще никакого значения, то есть NULL . В этом сценарии можно использовать тип bool? .
Назначение и объявление
Так как тип значения можно неявно преобразовать в соответствующий тип значения, допускающий значение NULL, вы назначаете значение переменной такого типа значения так же, как для базового типа значения. Вы можете также присвоить значение null . Пример:
Значение по умолчанию для типа значения, допускающего значение NULL, представляет null , то есть это экземпляр, свойство Nullable<T>.HasValue которого возвращает false .
Проверка экземпляра типа значения, допускающего значение NULL
Начиная с версии C# 7.0 можно использовать оператор с шаблоном типа как для проверки экземпляра типа, допускающего значение NULL, для null , так и для извлечения значения базового типа:
Вы всегда можете использовать следующие свойства только для чтения, чтобы проверить и получить значение переменной типа, допускающего значение NULL:
Nullable<T>.HasValue указывает, имеет ли экземпляр типа, допускающего значение NULL, значение своего базового типа.
Nullable<T>.Value возвращает значение базового типа, если HasValue имеет значение true . Если HasValue имеет значение false , свойство Value выдает исключение InvalidOperationException.
В следующем примере используется свойство HasValue , чтобы проверить, содержит ли переменная значение, перед его отображением:
Можно также сравнить переменную типа значения, допускающего значение NULL, с null вместо использования свойства HasValue , как показано в следующем примере:
Преобразование из типа значения, допускающего значение NULL, в базовый тип
Если необходимо присвоить значение типа, допускающего значение NULL, переменной типа значения, не допускающего значения NULL, может потребоваться указать значение, назначаемое вместо null . Для этого используйте оператор объединения со значением NULL (можно также применить метод Nullable<T>.GetValueOrDefault(T) для той же цели):
Если вы хотите использовать значение по умолчанию базового типа значения вместо, используйте Nullable<T>.GetValueOrDefault() метод.
Вы можете также явно привести тип значения, допускающий значение NULL, к типу, не допускающему значение NULL, как показано в примере ниже.
Во время выполнения, если значение типа значения, допускающего значение NULL, равно null , явное приведение вызывает исключение InvalidOperationException.
Тип T , не допускающий значение NULL, неявно преобразуется в соответствующий тип, допускающий значение NULL, T? .
Операторы с нулификацией
Предопределенные унарные и бинарные Операторы или любые перегруженные операторы, поддерживаемые типом значения, также поддерживаются соответствующим типом T? значения, допускающим значение null. Эти операторы, также называемые операторами с нулификацией, создают , если один или оба операнда имеют null значение; в противном случае оператор использует содержащиеся в его операндах значения для вычисления результата. Пример:
Для типа bool? предопределенные операторы & и | не следуют правилам, описанным в этом разделе: результат вычисления оператора может быть отличным от NULL, даже если один из операндов имеет значение null . См. подробнее о логических операторах, поддерживающих значение NULL в описании логических операторов.
Для операторов > <= сравнения,, и >= , если один или оба операнда имеют null значение, результат равен false ; в противном случае сравниваются вложенные значения операндов. Тут важно не полагать, что если какая-то операция сравнения (например, <= ) возвращает false , то противоположное сравнение ( > ) обязательно вернет true . В следующем примере показано, что 10
- не больше и не равно значению null ,
- не меньше чем null .
Для оператора равенства , если оба операнда равны null , результат будет равен true . Если один из операндов равен null , результат будет равен false . В противном случае сравниваются содержащиеся значения операндов.
Для оператора неравенства , если оба операнда равны null , результат будет равен false . Если один из операндов равен null , результат будет равен true . В противном случае сравниваются содержащиеся значения операндов.
Если между двумя типами данных определено пользовательское преобразование типов, то это же преобразование можно также использовать между соответствующими типами, допускающими значение NULL.
Упаковка-преобразование и распаковка-преобразование
Экземпляр типа T? значения, допускающего значение null, T? следующим образом:
- Если HasValue возвращает false , создается пустая ссылка.
- Если HasValue возвращает true , упаковывается соответствующее значение базового типа T , а не экземпляр Nullable<T>.
Можно распаковать упакованный тип значения T в соответствующий тип, допускающий значение NULL, T? , как показано в следующем примере:
Идентификация типа значений, допускающего значение NULL
В следующем примере показано, как определить, представляет ли экземпляр System.Type сконструированный тип значений, допускающий значение NULL, т. е. тип System.Nullable<T> с указанным параметром типа T :
Как показано в примере, для создания экземпляра используется оператор typeof .
Если вы хотите определить, принадлежит ли экземпляр к типу значений, допускающему значение NULL, не используйте метод Object.GetType для получения экземпляра Type для тестирования с помощью приведенного выше кода. При вызове Object.GetType метода для экземпляра типа значения, допускающего значение null, экземпляр Object.GetType в Object . Так как упаковка экземпляра типа значений, допускающего значение NULL, значение которого отлично от NULL, эквивалентна упаковке значения базового типа, GetType возвращается экземпляр Type, представляющий базовый тип типа значений, допускающего значение NULL:
Кроме того, не используйте оператор is, чтобы определить, принадлежит ли экземпляр к типу значений, допускающему значение NULL. Как показано в следующем примере, вы не можете отличить типы экземпляра типа значений, допускающего значение NULL, и его экземпляра базового типа с помощью оператора is :
Вместо этого используйте Nullable.GetUnderlyingType оператор from из первого примера и оператора Nullable.GetUnderlyingType , чтобы проверить, имеет ли экземпляр тип значения, допускающего значение null.
Методы, описанные в этом разделе, неприменимы в случае ссылочных типов, допускающих значения NULL.
Спецификация языка C#
Дополнительные сведения см. в следующих разделах статьи Спецификация языка C#: