Для указания способности иметь значение null в ссылочных типах, допускающих null, применяется тот же самый символ ?. Однако он не является сокращением для использования System.Nullable<T>, т.к. на месте Т могут находиться только типы значений. Не забывайте, что обобщения и ограничения рассматриваются в главе 10.
Включение ссылочных типов, допускающих null
Поддержка для ссылочных типов, допускающих null, управляется установкой контекста допустимости значения null. Это может распространяться на целый проект (за счет обновления файла проекта) или охватывать лишь несколько строк (путем применения директив компилятора). Вдобавок можно устанавливать следующие два контекста.
• Контекст с заметками о допустимости значения null: включает/отключает заметки о допустимости null(?) для ссылочных типов, допускающих null.
• Контекст с предупреждениями о допустимости значения null: включает/отключает предупреждения компилятора для ссылочных типов, допускающих null.
Чтобы увидеть их в действии, создайте новый проект консольного приложения по имени FunWithNullableReferenceTypes. Откройте файл проекта (если вы используете Visual Studio, тогда дважды щелкните на имени проекта в окне Solution Explorer или щелкните правой кнопкой мыши на имени проекта и выберите в контекстном меню пункт Edit Project file (Редактировать файл проекта)). Модифицируйте содержимое файла проекта для поддержки ссылочных типов, допускающих null, за счет добавления элемента <Nullable> (все доступные варианты представлены в табл. 4.5).
<Project Sdk="Microsoft .NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<b><Nullable>enable</Nullable></b>
</PropertyGroup>
</Project>
Элемент <Nullable> оказывает влияние на весь проект. Для управления меньшими частями проекта используйте директиву компилятора #nullable, значения которой описаны в табл. 4.6.
Ссылочные типы, допускающие null, в действии
Во многом из-за важности изменения ошибки с типами, допускающими значение null, возникают только при их ненадлежащем применении. Добавьте в файл Program.cs следующий класс:
(window.adrunTag = window.adrunTag || []).push({v: 1, el: 'adrun-4-390', c: 4, b: 390})
public class TestClass
{
public string Name { get; set; }
public int Age { get; set; }
}
Как видите, это просто нормальный класс. Возможность принятия значения null появляется при использовании данного класса в коде. Взгляните на показанные ниже объявления:
string? nullableString = null;
TestClass? myNullableClass = null;
Настройка в файле проекта помещает весь проект в контекст допустимости значения null, который разрешает применение объявлений типов string и TestClass с заметками о допустимости значения null (?). Следующая строка кода вызывает генерацию предупреждения (CS8600) из-за присваивания null типу, не допускающему значение null, в контексте допустимости значения null:
// Предупреждение CS8600 Converting null literal or possible null
// value to non-nullable type
// Преобразование литерала null или возможного значения null
// в тип, не допускающий null
TestClass myNonNullableClass = myNullableClass;
Для более точного управления тем, где в проекте находятся контексты допустимости значения null, с помощью директивы компилятора #nullable можно включать или отключать контекст (как обсуждалось ранее). В приведенном далее коде контекст допустимости значения null (установленный на уровне проекта) сначала отключается, после чего снова включается за счет восстановления настройки из файла проекта:
#nullable disable
TestClass anotherNullableClass = null;
// Предупреждение CS8632 The annotation for nullable reference types
// should only be used in code within a '#nullable' annotations
// Заметка для ссылочных типов, допускающих значение null,
// должна использоваться только в коде внутри
// #nullable enable annotations
TestClass? badDefinition = null;
// Предупреждение CS8632 The annotation for nullable reference types
// should only be used in code within a '#nullable' annotations
// Заметка для ссылочных типов, допускающих значение null,
// должна использоваться только в коде внутри
#nullable enable annotations
string? anotherNullableString = null;
#nullable restore
В заключение важно отметить, что ссылочные типы, допускающие значение null, не имеют свойств HasValue и Value, т.к. они предоставляются System.Nullable<T>.