Использование типов значений, допускающих значение NULL (руководство по программированию на C#)Using nullable value types (C# Programming Guide)

Типы значений, допускающие значение NULL, могут представлять все значения своего базового типа T, а также дополнительное значение NULL.Nullable value types are types that represent all the values of an underlying value type T, and an additional null value. Дополнительные сведения см. в статье Типы значений, допускающие значение NULL (руководство по программированию на C#).For more information, see the Nullable value types topic.

Примечание

В C# 8.0 появилась возможность использования ссылочных типов, допускающих значение NULL.C# 8.0 introduces the nullable reference types feature. Дополнительные сведения см. в статье Ссылочные типы, допускающие значение NULL.For more information, see Nullable reference types. Типы значений, допускающие значение NULL, доступны начиная с C# 2.The nullable value types are available starting with C# 2.

Вы можете ссылаться на тип значения, допускающий значение NULL, в любой из следующих взаимозаменяемых форм: Nullable<T> или T?.You can refer to a nullable value type in any of the following interchangeable forms: Nullable<T> or T?. T должно быть типом значения.T must be a value type.

Назначение и объявлениеDeclaration and assignment

Так как тип значения можно неявно преобразовать в соответствующий тип значения, допускающий значение NULL, вы назначаете значение такому типу значения так же, как его базовому типу значения.As a value type can be implicitly converted to the corresponding nullable value type, you assign a value to a nullable type as you would for its underlying value type. Вы также можете присвоить значение null.You also can assign the null value. Например:For example:

double? pi = 3.14;
char? letter = 'a';

int m2 = 10;
int? m = m2;

bool? flag = null;

// Array of nullable type:
int?[] arr = new int?[10];

Изучение значение типа, допускающего значение NULLExamination of a nullable type value

Используйте следующие свойства только для чтения, чтобы изучить экземпляр типа значения, допускающего значение NULL, со значением NULL и извлечь значение базового типа:Use the following readonly properties to examine an instance of a nullable value type for null and retrieve a value of an underlying type:

В коде в следующем примере используется свойство HasValue, чтобы проверить, содержит ли переменная значение, перед его отображением:The code in the following example uses the HasValue property to test whether the variable contains a value before displaying it:

int? x = 10;
if (x.HasValue)
{
    Console.WriteLine($"x is {x.Value}");
}
else
{
    Console.WriteLine("x does not have a value");
}

Вы также можете сравнить переменную типа значения, допускающего значение NULL, с null вместо использования свойства HasValue, как показано в следующем примере:You also can compare a variable of a nullable value type with null instead of using the HasValue property, as the following example shows:

int? y = 7;
if (y != null)
{
    Console.WriteLine($"y is {y.Value}");
}
else
{
    Console.WriteLine("y does not have a value");
}

Начиная с версии C# 7.0 для проверки и получения значения типа значения, допускающего значение NULL, можно использовать сопоставление шаблонов:Beginning with C# 7.0, you can use pattern matching to both examine and get a value of a nullable value type:

int? z = 42;
if (z is int valueOfZ)
{
    Console.WriteLine($"z is {valueOfZ}");
}
else
{
    Console.WriteLine("z does not have a value");
}

Преобразование из типа значения, допускающего значение NULL, в базовый типConversion from a nullable value type to an underlying type

Если вам нужно присвоить значение типа значения, допускающего значение NULL, типу, не допускающему значение NULL, используйте оператор объединения с NULL??, чтобы указать значение для присваивания, если значение типа значения, допускающего значение NULL, равно NULL (вы также можете использовать метод Nullable<T>.GetValueOrDefault(T)):If you need to assign a value of a nullable value type to a non-nullable type, use the null-coalescing operator ?? to specify the value to be assigned if a value of a nullable value type is null (you also can use the Nullable<T>.GetValueOrDefault(T) method to do that):

int? c = null;

// d = c, if c is not null, d = -1 if c is null.
int d = c ?? -1;
Console.WriteLine($"d is {d}");

Используйте метод Nullable<T>.GetValueOrDefault(), если значение, которое будет использоваться, когда значение типа значения, допускающего значение NULL, равно null, должно быть значением по умолчанию базового типа.Use the Nullable<T>.GetValueOrDefault() method if the value to be used when a value of a nullable value type is null should be the default value of the underlying value type.

Вы можете явно привести тип значения, допускающий значение NULL, к типу, не допускающему значение NULL.You can explicitly cast a nullable value type to a non-nullable type. Например:For example:

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.At run time, if the value of a nullable value type is null, the explicit cast throws an InvalidOperationException.

Тип, не допускающий значение NULL, неявно преобразуется в соответствующий тип, допускающий значение NULL.A non-nullable value type is implicitly converted to the corresponding nullable type.

ОператорыOperators

Предопределенные унарные и бинарные операторы, а также любые операторы, определенные программистом, которые существуют для типов значений, также можно использовать и с соответствующими типами, допускающими значение NULL.The predefined unary and binary operators and any user-defined operators that exist for value types may also be used by corresponding nullable types. Эти операторы возвращают значение null, если один или оба операнда имеют значение null. В противном случае оператор использует содержащиеся значения для вычисления результата.These operators produce null if one or both operands are null; otherwise, the operator uses the contained values to calculate the result. Например:For example:

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.For the bool? type, the predefined & and | operators don't follow the rules described in this section: the result of an operator evaluation can be non-null even if one of the operands is null. См. подробнее о логических операторах, поддерживающих значение NULL в описании логических операторов.For more information, see the Nullable Boolean logical operators section of the Boolean logical operators article.

Для операторов отношения (<, >, <=, >=), если один или оба операнда имеют значение null, результатом будет false.For the relational operators (<, >, <=, >=), if one or both operands are null, the result is false. Тут важно не полагать, что если какая-то операция сравнения (например, <=) возвращает false, то противоположное сравнение (>) обязательно вернет true.Do not assume that because a particular comparison (for example, <=) returns false, the opposite comparison (>) returns true. В следующем примере показано, что 10The following example shows that 10 is

  • не больше и не равно значению null,neither greater than or equal to null,
  • не меньше чем null.nor less than null.
int? num1 = 10;
int? num2 = null;
if (num1 >= num2)
{
    Console.WriteLine("num1 is greater than or equal to num2");
}
else
{
    Console.WriteLine("num1 >= num2 is false (but num1 < num2 also is false)");
}

if (num1 < num2)
{
    Console.WriteLine("num1 is less than num2");
}
else
{
    Console.WriteLine("num1 < num2 is false (but num1 >= num2 also is false)");
}

if (num1 != num2)
{
    Console.WriteLine("num1 != num2 is true!");
}

num1 = null;
if (num1 == num2)
{
    Console.WriteLine("num1 == num2 is true if the value of each is null");
}
// Output:
// num1 >= num2 is false (but num1 < num2 also is false)
// num1 < num2 is false (but num1 >= num2 also is false)
// num1 != num2 is true!
// num1 == num2 is true if the value of each is null

В приведенном выше примере видно, что проверка на равенство двух типов значения, допускающих значение NULL, которые оба равны NULL, всегда даст true.The above example also shows that an equality comparison of two nullable value types that are both null evaluates to true.

Дополнительные сведения см. в разделе о поднятых операторах в спецификации языка C#.For more information, see the Lifted operators section of the C# language specification.

Упаковка-преобразование и распаковка-преобразованиеBoxing and unboxing

Тип, допускающий значение NULL, упакован по следующим правилам:A nullable value type is boxed by the following rules:

  • Если HasValue возвращает false, создается пустая ссылка.If HasValue returns false, the null reference is produced.
  • Если HasValue возвращает true, упаковывается значение базового типа T, а не экземпляр Nullable<T>.If HasValue returns true, a value of the underlying value type T is boxed, not the instance of Nullable<T>.

Можно распаковать упакованный тип значения в соответствующий тип, допускающий значение NULL, как показано в следующем примере:You can unbox the boxed value type to the corresponding nullable type, as the following example shows:

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

См. такжеSee also