Примечание:
Я прочитал всю эту ветку и многие другие, но не могу найти столь подробный ответ, как этот.
По которому я полностью понял, «зачем использовать ?? и когда использовать ?? и как использовать ??.»
* Источник: 1010 *
Основа коммуникации Windows выпущена Крейгом МакМертри
ISBN 0-672-32948-4
Типы значений Nullable
Есть два распространенных обстоятельства, при которых один хотел бы знать,
значение было присвоено экземпляру типа значения. Первый - это когда экземпляр представляет значение в базе данных. В таком случае хотелось бы иметь возможность изучить экземпляр, чтобы выяснить, действительно ли значение присутствует в базе данных. Другое обстоятельство, которое в большей степени относится к предмету этой книги, - это когда экземпляр представляет элемент данных, полученный из некоторого удаленного источника. Опять же, из этого экземпляра хотелось бы определить, было ли получено значение для этого элемента данных.
.NET Framework 2.0 включает определение универсального типа, которое обеспечивает случаи, подобные этим, в которых требуется присвоить значение NULL экземпляру типа значения, и проверить, является ли значение экземпляра NULL. Это определение универсального типа - System.Nullable, которое ограничивает аргументы универсального типа, которые могут быть заменены на T, значениями типов.
Экземплярам типов, созданным из System.Nullable, может быть присвоено значение null; действительно, их значения по умолчанию равны нулю. Таким образом, типы построены из
System.Nullable может упоминаться как типы значений Nullable.
System.Nullable имеет свойство Value, с помощью которого значение, присвоенное экземпляру
построенный из него тип может быть получен, если значение экземпляра не равно нулю.
Поэтому можно написать:
System.Nullable<int> myNullableInteger = null;
myNullableInteger = 1;
if (myNullableInteger != null)
{
Console.WriteLine(myNullableInteger.Value);
}
Язык программирования C # предоставляет сокращенный синтаксис для объявления типов
построен из System.Nullable. Этот синтаксис позволяет сокращать:
System.Nullable<int> myNullableInteger;
до
int? myNullableInteger;
Компилятор предотвратит попытку присвоения значения типа значения NULL для обычного типа значения следующим образом:
int? myNullableInteger = null;
int myInteger = myNullableInteger;
Он запрещает это делать, потому что тип значения, допускающий значение NULL, может иметь значение NULL, которое в действительности будет иметь в этом случае, и это значение не может быть присвоено обычному типу значения. Хотя компилятор разрешил бы этот код,
int? myNullableInteger = null;
int myInteger = myNullableInteger.Value;
Второе утверждение вызовет исключение, потому что любая попытка
Доступ к свойству System.Nullable.Value является недопустимой операцией, если тип
построенный из System.Nullable не было назначено допустимое значение T, что не произошло в этом случае.
Вывод:
Один из правильных способов присвоения значения типа значения NULL для обычного типа значения - это использование свойства System.Nullable.HasValue, чтобы определить, было ли назначено допустимое значение T для типа NULL:
int? myNullableInteger = null;
if (myNullableInteger.HasValue)
{
int myInteger = myNullableInteger.Value;
}
Другой вариант - использовать этот синтаксис:
int? myNullableInteger = null;
int myInteger = myNullableInteger ?? -1;
С помощью которого обычному целому числу myInteger присваивается значение обнуляемого целого числа «myNullableInteger», если последнему было присвоено действительное целочисленное значение; в противном случае myInteger присваивается значение -1.