Использование допускающих значение NULL типов (руководство по программированию на C#)

Обновлен: Ноябрь 2007

Допускающие значение NULL типы могут представлять все значения лежащего в их основе типа, а также значение NULL. Допускающие значение NULL типы объявляются одним из следующих способов:

System.Nullable<T> variable

–либо–

T? variable

T — это тип, лежащий в основе допускающего значение NULL типа. Типом T может быть любой тип значения, включая struct, но не может быть ссылочный тип.

Примером случая, когда может использоваться допускающий значение NULL тип, может служить обычная переменная логического типа, которая может иметь два значения: true и false. Обозначающего "не определено" значения не существует. Во многих программных приложениях, в первую очередь в операциях с базами данных, переменные могут иметь неопределенное состояние. Например, поле базы данных может содержать значение true или false, но мажет также вообще не содержать какого-либо значения. Аналогично, ссылочные типы могут иметь значение null, обозначающее, что они не инициализированы.

Это несоответствие может создавать дополнительную работу по программированию, приводить к использованию дополнительных переменных для хранения информации о состоянии, применению специальных значений и т.д. Модификатор типа, преобразующий тип в допускающий значения NULL, позволяет языку C# создавать переменные типа значения, обозначающие неопределенное значение.

Примеры допускающих значение NULL типов

Любой тип значения может использоваться в качестве основы допускающего значение NULL типа. Например:

int? i = 10;
double? d1 = 3.14;
bool? flag = null;
char? letter = 'a';
int?[] arr = new int?[10];

Члены допускающих значение NULL типов

Каждый экземпляр допускающего значение NULL типа имеет два общих предназначенных только для чтения свойства:

  • HasValue

    Свойство HasValue имеет тип bool. Это свойство имеет значение true, если переменная содержит определенное значение.

  • Value

    Свойство Value имеет тот же тип, что и лежащий в основе тип. Если свойство HasValue имеет значение true, то свойство Value содержит имеющее смысл значение. Если свойство HasValue имеет значение false, то доступ к свойству Value будет приводить к формированию ошибки InvalidOperationException.

В этом примере член HasValue используется для выполнения проверки, содержит ли переменная какое-либо значение, прежде чем пытаться его показать.

int? x = 10;
if (x.HasValue)
{
    System.Console.WriteLine(x.Value);
}
else
{
    System.Console.WriteLine("Undefined");
}

Проверка переменной может быть также выполнена способом, показанным в следующем примере:

int? y = 10;
if (y != null)
{
    System.Console.WriteLine(y.Value);
}
else
{
    System.Console.WriteLine("Undefined");
}

Явные преобразования

Допускающий значение NULL тип может быть приведен к обычному типу либо явным образом с помощью приведения, либо с помощью свойства Value. Например:

int? n = null;

//int m1 = n;      // Will not compile.
int m2 = (int)n;   // Compiles, but will create an exception if x is null.
int m3 = n.Value;  // Compiles, but will create an exception if x is null.

Если определенное пользователем преобразование определено между двумя типами данных, то это же преобразование может быть также использовано с допускающими значение NULL версиями этих типов данных.

Неявные преобразования

Переменной допускающего значение NULL типа может быть присвоено значение NULL с помощью ключевого слова null, как показано в следующем примере:

int? n1 = null;

Преобразование из обычного типа в допускающий значение NULL тип является неявным.

int? n2;
n2 = 10;  // Implicit conversion.

Операторы

Существующие для типов значений предварительно определенные унарные и бинарные операторы, а также определенные пользователем операторы могут также использоваться допускающими значение NULL типами. Эти операторы создают значение NULL, если операнды имеют значение NULL; иначе оператор использует для вычисления результата содержащееся значение. Например:

int? a = 10;
int? b = null;

a++;         // Increment by 1, now a is 11.
a = a * 10;  // Multiply by 10, now a is 110.
a = a + b;   // Add b, now a is null.

Если при выполнении сравнения с допускающими значение NULL типами один из допускающих значение NULL типов содержит null, то результатом сравнения всегда является false. Следовательно, важно не считать, что если результатом сравнения является false, то противоположным случаем является true. Например:

int? num1 = 10;
int? num2 = null;
if (num1 >= num2)
{
    System.Console.WriteLine("num1 is greater than or equal to num1");
}
else
{
    // num1 is NOT less than num2
}

Заключение в инструкции else является недопустимым, потому что num2 содержит null и, следовательно, не содержит какого-либо значения.

Сравнение двух допускающих значение NULL типов, оба из которых содержат null, будет давать результат true.

Оператор ??

Оператор ?? определяет значение по умолчанию, возвращаемое при присвоении допускающего значение NULL типа не допускающему значение NULL типу.

int? c = null;

// d = c, unless c is null, in which case d = -1.
int d = c ?? -1;

Этот оператор может также использоваться с несколькими допускающими значение NULL типами. Например:

int? e = null;
int? f = null;

// g = e or f, unless e and f are both null, in which case g = -1.
int g = e ?? f ?? -1;

Тип bool?

Допускающий значение NULL тип bool? может содержать три значения: true, false и null. Сведения о том, как выполняется приведение из bool? в bool, см. в разделе Практическое руководство. Безопасное приведение bool? к bool (руководство по программированию в C#).

Допускающие значение NULL логические типы аналогичны логическим типам переменных, используемым в языке SQL. Для обеспечения согласованности результатов выполнения операторов & и | с имеющим три значения логическим типом языка SQL предусмотрены следующие предварительно определенные операторы:

bool? operator &(bool? x, bool? y)

bool? operator |(bool? x, bool? y)

Результаты выполнения этих операторов приведены в следующей таблице:

X

y

x&y

x|y

true

true

true

true

true

false

false

true

true

null

null

true

false

true

false

true

false

false

false

false

false

null

false

null

null

true

null

true

null

false

false

null

null

null

null

null

См. также

Основные понятия

Руководство по программированию в C#

Ссылки

Типы, допускающие значения NULL (руководство по программированию на C#)

Упаковка типов, допускающих значения NULL (Руководство по программированию на C#)