В этой статье мы рассмотрим функцию ссылочных типов, допускающих значение NULL, в C # 8.

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

Традиционно разработчики считали, что ссылочный тип предназначен для приема как ненулевых, так и нулевых значений, и не требовалось какой-либо явной обработки, и, к сожалению, это соображение является одной из основных коренных причин знаменитого «исключения нулевой ссылки».

Основная причина NullReferenceException заключается в том, что рассматриваемая ссылка не имеет действительного адреса памяти и, следовательно, при разыменовании (чтение значения из адреса памяти) она не знает, откуда читать значение, и, следовательно, не работает.

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

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

Обзор контекста, допускающего значение NULL

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

  • Контекст аннотации, допускающей значение NULL: он может быть включен или отключен для любой данной исходной строки. Вы можете рассмотреть компиляторы до C # 8 для отключенного контекста аннотации.
  • Контекст предупреждений, допускающих значение NULL: для него может быть установлено значение «включено», «отключено» или «только безопасно». Контекст предупреждений, допускающих значение NULL, определяет предупреждения, сгенерированные компилятором с помощью анализа потока.

Аннотации, допускающие значение NULL, и контекст предупреждения могут быть установлены для проекта с помощью элемента Nullable в вашем файле csproj. Эти параметры определяют, как компилятор интерпретирует допустимость значений NULL для типов и какие предупреждения генерируются.

Контекст, допускающий значение NULL, устанавливается в файле csproj следующим образом.

<LangVersion>8.0</LangVersion>  
<Nullable>enable</Nullable> 

В следующей таблице показана конфигурация аннотации, допускающей значение NULL, и контекст предупреждения основан на атрибуте Nullable в файле csproj.

таблица 3

Теперь давайте разберемся в значении этих значений в контексте аннотации и предупреждения.

Если значение элемента, допускающего значение NULL, установлено как enable, включен контекст аннотации, допускающий значение NULL, и контекст предупреждения, допускающий значение NULL. В результате переменные ссылочного типа (например, строка) не допускают значения NULL. Все предупреждения о допустимости пустых значений включены.

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

Если вы устанавливаете значение Nullable как safeonly, вы в основном устанавливаете контекст аннотации, допускающий значение NULL, как включенный, а контекст предупреждения, допускающий значение NULL, как safeonly. По сути, это означает, что переменные ссылочного типа не допускают значения NULL и разрешены только предупреждения о допустимости значений NULL.

Устанавливая значение Nullable в качестве предупреждений, вы в конечном итоге устанавливаете контекст аннотации, допускающий значение NULL, как отключенный, а контекст предупреждения, допускающий значение NULL, как включенный. Из-за этого переменные ссылочного типа не обращают внимания (как и в версии до C # 8), однако все предупреждения о допустимости пустых значений включены.

Наконец, когда вы устанавливаете запись, допускающую значение NULL, как safeonlywarnings, контекст аннотации, допускающий значение NULL, устанавливается как отключенный, а контекст предупреждения, допускающий значение NULL, устанавливается как safeonly. Это означает, что переменные ссылочного типа не обращают внимания (как и в версии до C # 8) и включены все предупреждения о допустимости значений NULL.

Помимо файла csproj, эти параметры также можно настроить в исходном коде, а ниже приведен список кода, который можно использовать. Вы можете использовать директивы для установки тех же контекстов в любом месте вашего проекта следующим образом.

  • #nullable enable: устанавливает для контекста аннотации, допускающего значение NULL, и контекста предупреждения, допускающего значение NULL, значение включено.
  • #nullable disable: устанавливает контекст аннотации, допускающий значение NULL, и предупреждение, допускающее значение NULL.

контекст отключен. Это то же самое, что и в версии до C# 8.

  • #nullable safeonly: установите для контекста аннотации, допускающего значение NULL, значение enabled, а для контекста предупреждения — значение safeonly.

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

  • #pragma warning disable nullable: установите для контекста предупреждения, допускающего значение null, значение disabled.
  • #pragma warning enable nullable: установите для контекста предупреждения, допускающего значение NULL, значение включено.
  • #pragma warning safeonly nullable: устанавливает для контекста предупреждения, допускающего значение null, значение safeonly.

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

  • Поведение такое же, как и в предыдущих версиях C #.
  • Подход с использованием ссылок, допускающих значение NULL, не существует, поскольку всем ссылочным переменным можно присвоить значение NULL.
  • При разыменовании переменной ссылочного типа предупреждения не генерируются. Оператор, допускающий нулевое значение (т.е.!), Использовать нельзя.

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

  • Любая переменная ссылочного типа является ссылкой, не допускающей значения NULL. Любая ссылка, не допускающая значения NULL, может быть безопасно разыменована.
  • Любой ссылочный тип, допускающий значение NULL, может иметь значение NULL. Если после статического анализа известно, что значение не равно нулю, компилятор предупредит вас.
  • Вы можете использовать нулевой оператор! чтобы объявить, что ссылка, допускающая значение NULL, не является нулевой.

Примечание

Пустой оператор (!) — это анти-шаблон, и вам следует избегать его использования. Он отключает только проверки компилятора, однако во время выполнения значение все еще может быть нулевым. Его следует использовать только в редких случаях, когда компилятор не может определить, что значение, допускающее значение NULL, на самом деле не допускает значения NULL.

Использование в коде контекста, допускающего значение NULL

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


    public static void ExecuteNonNullableReferenceType()  
    {  
       #nullable enable  
       string name = null;  
       var myName = name.ToString();   
       #nullable restore  
    }  

А вот и предупреждения из приведенного выше кода.

Working With Nullable Reference Types In C# 8.0 1111

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

Теперь давайте внесем небольшое изменение в приведенный выше код и добавим Null Forgiving Operator (!) И посмотрим на результат.


    public static void ExecuteNullableReferenceType2()  
    {  
       #nullable enable  
       string? name = null;  
       var myName = name!.ToString(); // Null Forgiving Operator   
       #nullable restore  
    }  

Результат выглядит следующим образом:

Working With Nullable Reference Types In C#1 22222

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

Примечание

Контексты аннотаций и предупреждений, допускающие значение NULL, по умолчанию отключены. Это означает, что ваш существующий код компилируется без изменений и без каких-либо новых предупреждений. Однако, если вы хотите применить дизайн на основе намерений, рекомендуется включить аннотации, допускающие значение NULL, и контексты предупреждений.

Резюме

В этой статье мы рассмотрели предысторию ссылочных типов, допускающих значение NULL, и выяснили, почему они необходимы. Позже мы глубоко погрузились в контекст аннотаций, допускающих значения NULL, и предупреждений, и где они могут быть установлены. Мы также видели использование оператора Null Forgiving, который изменяет поведение компилятора. Очевидно, что ссылочные типы, допускающие значение NULL, обеспечивают конструкцию на основе намерений и могут помочь уменьшить исключение нулевой ссылки во время выполнения.