Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Тип значений, допускающий значение NULL, или T?, представляет все значения своего базового типа значенияT, а также дополнительное значение NULL. Например, можно присвоить переменной bool? любое из следующих трех значений: true, false или null. Базовый тип T значения не может быть типом значения NULL.
Справочные документы на языке C#, выпущенные последней версией языка C#. Она также содержит начальную документацию по функциям в общедоступных предварительных версиях для предстоящего языкового выпуска.
Документация определяет любую функцию, впервые представленную в последних трех версиях языка или в текущих общедоступных предварительных версиях.
Подсказка
Чтобы узнать, когда функция впервые появилась в C#, ознакомьтесь со статьей по журналу версий языка C#.
Типы, допускающие значение NULL, представляют собой экземпляры универсальной структуры System.Nullable<T>. Вы можете ссылаться на тип значения, допускающий значение NULL, с базовым типом T в любой из следующих взаимозаменяемых форм: Nullable<T> или T?.
Как правило, используйте тип значения, допускающего значение NULL, если необходимо представить неопределенное значение базового типа значения. Например, логическая переменная (или bool) может иметь только значения true или false. Однако в некоторых приложениях значение переменной может быть неопределенным или отсутствовать. Например, поле базы данных может содержать true или falseне содержать значения вообще. NULL В этом сценарии можно использовать тип bool?.
Назначение и объявление
Так как тип значения неявно преобразуется в соответствующий тип значения, допускающего значение NULL, можно назначить значение переменной типа значения, допускающего значение NULL, так как это делается для его базового типа значения. Вы можете также присвоить значение null. Например:
double? pi = 3.14;
char? letter = 'a';
int m2 = 10;
int? m = m2;
bool? flag = null;
// An array of a nullable value type:
int?[] arr = new int?[10];
Значение по умолчанию типа значения, допускающего значение NULL, представляет null. Это экземпляр, свойство которого Nullable<T>.HasValue возвращается false.
Проверка экземпляра типа значения, допускающего значение NULL
Чтобы проверить экземпляр типа null значения, допускающего значение NULL, и получить значение базового типа, используйте is оператор с шаблоном типа:
int? a = 42;
if (a is int valueOfA)
{
Console.WriteLine($"a is {valueOfA}");
}
else
{
Console.WriteLine("a does not have a value");
}
// Output:
// a is 42
Для проверки и получения значения переменной типа значения, допускающего значение NULL, всегда можно использовать следующие свойства только для чтения:
Nullable<T>.HasValue показывает, имеет ли экземпляр типа значения NULL значение своего базового типа.
Nullable<T>.Value возвращает значение базового типа, если HasValue имеет значение
true. Если HasValue имеет значениеfalse, свойство Value выдает исключение InvalidOperationException.
В следующем примере свойство используется HasValue для проверки того, содержит ли переменная значение перед отображением.
int? b = 10;
if (b.HasValue)
{
Console.WriteLine($"b is {b.Value}");
}
else
{
Console.WriteLine("b does not have a value");
}
// Output:
// b is 10
Можно также сравнить переменную типа значения, допускающего значение NULL, с null вместо использования свойства HasValue, как показано в следующем примере:
int? c = 7;
if (c != null)
{
Console.WriteLine($"c is {c.Value}");
}
else
{
Console.WriteLine("c does not have a value");
}
// Output:
// c is 7
Преобразование из типа значения, допускающего значение NULL, в базовый тип
Если вы хотите назначить значение типа значения, допускающего значение NULL, переменной типа не допускающего значение NULL, может потребоваться указать значение, которое следует назначить вместо null. Для этого используйте оператор ??объединения null. Вы также можете использовать Nullable<T>.GetValueOrDefault(T) метод для той же цели:
int? a = 28;
int b = a ?? -1;
Console.WriteLine($"b is {b}"); // output: b is 28
int? c = null;
int d = c ?? -1;
Console.WriteLine($"d is {d}"); // output: d is -1
Если вы хотите использовать значение по умолчанию базового типа значения вместо null, воспользуйтесь методом Nullable<T>.GetValueOrDefault().
Вы можете также явно привести тип значения, допускающий значение NULL, к типу, не допускающему значение NULL, как показано в примере ниже.
int? n = null;
//int m1 = n; // Doesn't compile
int n2 = (int)n; // Compiles, but throws an exception if n is null
Во время выполнения, если значение типа значения, допускающего значение NULL, равно null, явное приведение вызывает исключение InvalidOperationException.
Тип T, не допускающий значение NULL, неявно преобразуется в соответствующий тип, допускающий значение NULL, T?.
Операторы с нулификацией
Тип T? значения, допускающий значение NULL, поддерживает предопределенные унарные и двоичные операторы или любые перегруженные операторы, поддерживаемые типом T значения. Эти операторы, также известные как снятые операторы, возвращаются null , если один или оба операнда являются null. В противном случае оператор использует содержащиеся значения операндов для вычисления результата. Например:
int? a = 10;
int? b = null;
int? c = 10;
a++; // a is 11
a = a * c; // a is 110
a = a + b; // a is null
Примечание.
Для типа bool? предопределенные операторы & и | не следуют правилам, описанным в этом разделе: результат вычисления оператора может быть отличным от NULL, даже если один из операндов имеет значение null. См. подробнее о логических операторах, поддерживающих значение NULL в описании логических операторов.
Для операторов< сравнения , и >=, ><=если один или оба операнда являются, результатом являетсяnullfalse. В противном случае сравниваются содержащиеся значения операндов. Не предполагайте, что, поскольку определенное сравнение (например, <=) возвращает, обратное falseсравнение (>) возвращается true. В следующем примере показано, что 10
- не больше и не равно значению
null, - не меньше чем
null.
int? a = 10;
Console.WriteLine($"{a} >= null is {a >= null}");
Console.WriteLine($"{a} < null is {a < null}");
Console.WriteLine($"{a} == null is {a == null}");
// Output:
// 10 >= null is False
// 10 < null is False
// 10 == null is False
int? b = null;
int? c = null;
Console.WriteLine($"null >= null is {b >= c}");
Console.WriteLine($"null == null is {b == c}");
// Output:
// null >= null is False
// null == null is True
Для оператора== равенства, если оба операнда являются, результатом является nulltrue. Если только один из операндов является null, результатом является false. В противном случае сравниваются содержащиеся значения операндов.
Для оператора!= неравенства, если оба операнда являются, результатом является nullfalse. Если только один из операндов является null, результатом является true. В противном случае сравниваются содержащиеся значения операндов.
Если определяемое пользователем преобразование существует между двумя типами значений, то одно и то же преобразование также можно использовать между соответствующими типами значений, допускающих значение NULL.
Упаковка-преобразование и распаковка-преобразование
Следующие правила применяются при поле экземпляра типа T?значения, допускающего значение NULL:
- Если HasValue возвращается
false, операция бокса возвращает пустую ссылку. - Если HasValue возвращается
true, операция бокса выводит соответствующее значение базового типаTзначения, а не экземпляр Nullable<T>.
Можно распаковать упакованный тип значения T в соответствующий тип, допускающий значение NULL, T?, как показано в следующем примере:
int a = 41;
object aBoxed = a;
int? aNullable = (int?)aBoxed;
Console.WriteLine($"Value of aNullable: {aNullable}");
object aNullableBoxed = aNullable;
if (aNullableBoxed is int valueOfA)
{
Console.WriteLine($"aNullableBoxed is boxed int: {valueOfA}");
}
// Output:
// Value of aNullable: 41
// aNullableBoxed is boxed int: 41
Идентификация типа значений, допускающего значение NULL
В следующем примере показано, как определить, представляет ли экземпляр System.Type сконструированный тип значений, допускающий значение NULL, т. е. тип System.Nullable<T> с указанным параметром типа T:
Console.WriteLine($"int? is {(IsNullable(typeof(int?)) ? "nullable" : "non nullable")} value type");
Console.WriteLine($"int is {(IsNullable(typeof(int)) ? "nullable" : "non-nullable")} value type");
bool IsNullable(Type type) => Nullable.GetUnderlyingType(type) != null;
// Output:
// int? is nullable value type
// int is non-nullable value type
Как показано в примере, при помощи оператора typeof можно создать экземпляр System.Type.
Если вы хотите определить, является ли экземпляр типом значения NULL, не используйте Object.GetType метод для Type тестирования экземпляра с помощью предыдущего кода. При вызове метода Object.GetType в экземпляре типа значений, допускающего значение NULL, экземпляр упаковывается в Object. Так как поле экземпляра значения, отличного от NULL, эквивалентно боксу базового типа, GetType возвращает Type экземпляр, представляющий базовый тип значения, допускающего значение NULL:
int? a = 17;
Type typeOfA = a.GetType();
Console.WriteLine(typeOfA.FullName);
// Output:
// System.Int32
Кроме того, не используйте оператор is, чтобы определить, принадлежит ли экземпляр к типу значений, допускающему значение NULL. Как показано в следующем примере, нельзя различать типы экземпляра типа значений, допускающего значение NULL, и его базовый is экземпляр типа с помощью оператора:
int? a = 14;
if (a is int)
{
Console.WriteLine("int? instance is compatible with int");
}
int b = 17;
if (b is int?)
{
Console.WriteLine("int instance is compatible with int?");
}
// Output:
// int? instance is compatible with int
// int instance is compatible with int?
Вместо этого используйте Nullable.GetUnderlyingType метод из первого примера и оператор typeof , чтобы проверить, является ли экземпляр типом значения NULL.
Примечание.
Методы, описанные в этом разделе, не применяются к типам ссылок, допускающих значение NULL.
Спецификация языка C#
Дополнительные сведения см. в следующих разделах статьи Спецификация языка C#:
- Типы, допускающие значения NULL
- Операторы с нулификацией
- Неявные преобразования, допускающие значения NULL
- Явные преобразования, допускающие значения NULL
- Операторы преобразования с нулификацией
См. также
- What exactly does 'lifted' mean? (Что означает термин "расширенные"?)
- System.Nullable<T>
- System.Nullable
- Nullable.GetUnderlyingType
- Ссылочные типы, допускающие значение NULL