Что за сообщение null

Обновлено: 25.06.2024

В PowerShell состояние $null часто кажется простым, но оно имеет много нюансов. Давайте подробно рассмотрим $null и выясним, что означает неожиданное получение значения $null .

Что означает NULL

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

$null в PowerShell

$null — это автоматическая переменная в PowerShell, используемая для представления значения NULL. Ее можно назначать переменным и использовать в сравнениях, а также в качестве заполнителя для значения NULL в коллекции.

В PowerShell $null считается объектом со значением NULL, что отличается от трактовки этого понятия в других языках.

Примеры использования $null

Всякий раз, когда вы пытаетесь использовать переменную, которая не была инициализирована, ее значением будет $null . Это одна из самых распространенных причин, по которой значения $null появляются в коде.

Если вы неправильно указали имя переменной, PowerShell не распознает ее и присвоит ей значение $null .

Значения $null также появляются при выполнении команд, которые не выдают результатов.

Интерпретация $null

Значения $null обрабатываются в коде по-разному, в зависимости от того, где они находятся.

В строках

Если в строке используется $null , то это пустое значение (или пустая строка).

Так можно легко обнаружить пустые строки и значения $null .

В числовом уравнении

Когда значение $null используется в числовом уравнении, результаты будут недействительными, если не будет возвращена ошибка. Иногда $null значит 0 , но в других случаях полученный результат будет приравнен к $null . Ниже приведен пример с умножением, результатом которого может быть как 0, так и $null в зависимости от порядка значений.

Вместо коллекции

Коллекция позволяет использовать индекс для доступа к значениям. При попытке индексировать в коллекцию, которая фактически является null , вы получите ошибку Cannot index into a null array .

Если у вас есть коллекция, но вы пытаетесь получить доступ к элементу, который отсутствует в коллекции, вы получите результат $null .

Вместо объекта

При попытке доступа к свойству или подсвойству объекта, у которого нет указанного свойства, вы получите значение $null , как и в случае доступа к неопределенной переменной. При этом не имеет значения, является ли переменная $null или фактическим объектом.

Метод в выражении со значением NULL

Вызов метода для объекта $null вызывает исключение RuntimeException .

Проверка на соответствие $null

Вы могли заметить, что при проверке на $null я всегда указываю $null слева в своих примерах. Это сделано специально, как и рекомендуется в PowerShell. Возможны ситуации, когда размещение $null справа не дает ожидаемого результата.

Взгляните на следующий пример и постарайтесь предсказать результаты:

В данном случае $value является массивом, содержащим $null . -eq проверяет каждое значение в массиве и возвращает совпадающее значение $null . Результатом этого будет $false . -ne возвращает все, что не соответствует $null , и в этом случае не имеет результата (результатом также будет $false ). Ни одно из условий не является $true , тогда как кажется, что одно из них должно быть таким.

Мы можем не только создать значение, допускающее, чтобы оба условия были $false , но и такое, когда оба из них станут $true . Матиас Йессен (Mathias Jessen, @IISResetMe) опубликовал Хорошая статья на эту тему.

PSScriptAnalyzer и VSCode

Модуль PSScriptAnalyzer имеет правило для проверки таких коллизий, называющееся PSPossibleIncorrectComparisonWithNull .

Поскольку VS Code также использует правила PSScriptAnalyser, в редакторе такие фрагменты кода выделяются и считаются проблемой.

Простая проверка if

Проверку на несоответствие значению $null обычно выполняют с помощью простой инструкции if() без сравнения.

Если значение равно $null , то результатом будет $false . Это выглядит просто, но только на первый взгляд. Я понимаю эту строку кода как:

Но это еще не все. На самом деле строка значит следующее:

Если $value не имеет значение $null , 0 , $false или empty string .

Ниже приведен более полный пример этой инструкции.

Вполне допустимо использовать базовую проверку if , помня не только о значении переменной, но и о том, что другие значения считаются $false .

Несколько дней назад я столкнулся с этой проблемой при рефакторинге кода. В нем присутствовала базовая проверка такого типа.

Мне было нужно присвоить значение свойству объекта только в том случае, если он существует. В большинстве случаев первоначальному объекту было присвоено значение, для которого возвращался результат $true при выполнении if . Но я столкнулся с проблемой, когда значение иногда не устанавливалось. Я начал отладку и обнаружил, что у объекта есть свойство, но это пустое строковое значение. Это вообще не позволяло ему обновляться в соответствии с предыдущей логикой. Поэтому я добавил необходимую проверку на соответствие $null , и все заработало.

Такие мелкие ошибки трудно обнаружить, что научило меня специально проверять значения на соответствие $null .

$null.Count

Если вы попытаетесь получить доступ к свойству по значению $null , это свойство также будет $null . Свойство count является исключением из этого правила.

Если у вас есть значение $null , то count равняется 0 . Это специальное свойство добавляется PowerShell.

[PSCustomObject] Count

Почти у всех объектов в PowerShell есть свойство Count. Одним из примечательных исключений является [PSCustomObject] в Windows PowerShell 5.1 (что было исправлено в PowerShell 6.0). У него нет свойства Count, поэтому при попытке его использования вы получаете значение $null . Я вспомнил это к тому, чтобы вы не пытались использовать .Count вместо проверки $null .

Выполнение этого примера в Windows PowerShell 5.1 и PowerShell 6.0 дает разные результаты.

Пустое значение NULL

Существует один особый тип $null , который отличается от остальных. Я буду называть его пустым значением $null , тогда как фактически это System.Management.Automation.Internal.AutomationNull. Такое пустое значение $null вы получаете в результате выполнения функции или блока скрипта, которые не возвращают ничего (возвращают void).

Если сравнить его с $null , вы получите значение $null . При использовании в вычислении, где требуется значение, его значение всегда будет $null . Но если поместить его в массив, он будет считаться пустым массивом.

Можно создать массив с одним значением $null , при этом его свойство count будет равно 1 . Но если поместить пустой результат в массив, он не будет считаться элементом, а Count будет иметь значение 0 .

Если пустое значение $null вы обрабатываете как коллекцию, она будет считаться пустой.

Если передать пустое значение в параметр функции, который не является строго типизированным, PowerShell по умолчанию приводит значение Nothing к значению $null . Это означает, что внутри функции значение будет обрабатываться как $null вместо типа System.Management.Automation.Internal.AutomationNull.

Pipeline

Различия особенно заметны при работе с конвейером. Вы можете передать в него значение $null , но не пустое значение $null .

В зависимости от кода следует учитывать $null в логике.

В любом случае сначала выполните проверку на соответствие $null :

  • В конвейере отфильтруйте значение NULL( . | Where | . ).
  • Задайте его обработку с помощью функции конвейера.

foreach

Одна из моих любимых возможностей метода foreach — это то, что он не выполняет перечисление по коллекции $null .

Это избавляет от необходимости проверять коллекцию на соответствие $null перед ее перечислением. Если у вас есть коллекция со значениями $null , объект $node также может иметь значение $null .

Оператор foreach начал так работать с версии PowerShell 3.0. Если у вас предыдущая версия, такой режим работы в ней не поддерживается. Это одно из важных отличий, которое необходимо учитывать при обратном портировании кода для совместимости с версией 2.0.

Типы значений

Технически только ссылочные типы могут принимать значение $null . Но благодаря стараниям разработчиков PowerShell мы можем указывать любой тип для переменных. Если вы решили строго типизировать значения, задать $null не получится. PowerShell преобразует $null в значение по умолчанию для многих типов.

У некоторых типов не предусмотрено значение для преобразования из $null . Такие типы при обработке вызывают ошибку Cannot convert null to type .

Параметры функции

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

Как только вы задаете тип параметра string , его значение не может быть $null . Обычно принято выполнять проверку на соответствие $null , чтобы выяснить, предоставил ли пользователь значение.

Если значение не указано, $Value является пустой строкой '' . Вместо этого используйте автоматическую переменную $PSBoundParameters.Value .

$PSBoundParameters содержит только параметры, указанные при вызове функции. Для проверки свойства можно также использовать метод ContainsKey .

IsNotNullOrEmpty

Если значение является строкой, можно использовать статическую строковую функцию для проверки того, является ли значение $null или пустой строкой одновременно.

Я часто так делаю, когда знаю, что тип значения должен быть строкой.

Когда я выполняю проверку на соответствие $null

Когда я пишу код, то стараюсь предусмотреть все варианты. Вызывая функцию и присваивая ее переменной, я проверяю ее на соответствие $null .

Я предпочитаю использовать if или foreach , а не try/catch . Не поймите мене неправильно, я часто пользуюсь try/catch . Но если я могу задать проверку на состояния ошибки или пустой набор результатов, я могу обеспечить обработку реальных исключений.

Я стараюсь проверять на соответствие $null перед индексацией в значение или вызовом методов для объекта. Оба этих действия не срабатывают для объектов $null , поэтому сначала нужно их проверить. Эти сценарии уже рассматривались ранее в этой статье.

Сценарий без результатов

Важно помнить, что разные функции и команды по-разному обрабатывают сценарий без результатов. Многие команды PowerShell возвращают пустое значение $null и ошибку в потоке ошибок, тогда как другие вызывают исключения или предоставляют объект состояния. Вам нужно выяснить, как используемые вами команды работают со сценариями без результатов и сценариями ошибок.

Инициализация значения $null

У меня выработалась привычка инициализировать все переменные перед их использованием. В других языках это обязательно. В начале функции или цикла foreach я определяю все используемые значения.

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

Здесь предполагается, что Get-Something возвращает либо результат, либо пустое значение $null . Если возникает ошибка, она регистрируется в журнале. Перед ее обработкой мы проводим проверку, чтобы убедиться в том, что получен допустимый результат.

Ошибка в этом коде возникает, когда Get-Something создает исключение и не присваивает $result значение. Выполнение кода завершается ошибкой до назначения, поэтому переменной $result даже не присваивается значение $null . Переменная $result сохраняет допустимое значение $result из предыдущих итераций. В этом примере Update-Something выполняется несколько раз с одним и тем же объектом.

Устранить проблему мне удалось после того, как я задал $null для $result прямо в цикле foreach.

Проблемы с областью действия

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

Неинициализированная переменная в функции не имеет значения $null , если ей присвоено значение в родительской области. Родительской областью может быть другая функция, которая вызывает эту функцию и использует такие же имена переменных.

Если взять тот же пример Do-something и удалить из него цикл, то код будет таким:

Если вызов Get-Something возвращает исключение, тогда проверка на соответствие $null найдет $result в Invoke-Something . Инициализация значения внутри функции устраняет эту ошибку.

Именовать переменные сложно, и разработчики часто используют одинаковые имена переменных в разных функциях. Например, я постоянно использую $node , $result и $data . Из-за этого значения из других областей могут легко появиться в тех местах, где их не должно быть.

Перенаправление вывода в $null

Все вышесказанное касалось значений $null , но тема не будет раскрыта, если не объяснить, как перенаправлять выходные данные в $null . Бывают команды, выходные данные или объекты которых нужно опустить. Это можно сделать, перенаправив выходные данные в $null .

Out-Null

Команда Out-Null — это встроенный способ перенаправления данных конвейера в $null .

Назначение в $null

Результатам команды можно назначить значение $null , что будет аналогично использованию Out-Null .

Поскольку $null является постоянным значением, перезаписать его нельзя. Мне не нравится такая реализация в коде, но этот способ часто работает быстрее, чем Out-Null .

Перенаправление в $null

Можно также использовать оператор перенаправления для отправки выходных данных в $null .

Сводка

Здесь я много рассказал о $null, но статья получилась несколько отрывочной. Все потому, что значения $null могут встречаться повсюду в PowerShell, и их трактовка будет обусловлена конкретным местом. Надеюсь, теперь вы лучше разобрались с $null и непонятными ситуациями, где это состояние может повстречаться.

Но есть СМС, которые непонятны и одно из таких — СМС, содержанием которого является nullnullnull или null null null — нет никакой подсказки что это за SMS, а в интернете информации как кот наплакал.

Номер СМС Описание
2317 Предположительно МТС-ИНФО (уточнить у оператора). Вроде как подключается всем абонентам. Также телефон может отправлять смс на этот номер. Деньги снимать не должны, но всякое бывает. Чтобы исключить любые писание — звоним оператору и включаем функцию Запрет контента. Один юзер звонил оператору и ему ответили, что номер 2317 используется для передачи служебной информации, а также для обновления приложений и меню сим-карты.
4153 Информация не найдена. Возможно это в некотором смысле коллега первого номера 2317.
1453 и 1307 Скорее всего тоже MTS Info.

Первое что мне пришло на ум — содержание в виде nullnullnull сообщает об неудаче при выполнении операции, функции, обработке. То есть например вы заказали услугу. Но она не была предоставлена из-за ошибки и услуга вернула ответ nullnullnull. Но это только мои мысли, предположение.

Лен, я сама с этим словом сначала засмучалась, а потом поняла, что это система так справляется с нашим диалогом, если приходит этот "нул", то я обновляю страницу и все читаемо!

Счастливая история Мудрец (17355) так смотрю тут все по-настоячему хотели помочь. хотяб пообщаться :)))))

null, Verb (глагол)

null, Adjective (прилагательное)

Сегодня впервые столкнулся. Посчитал, что мне ответили таким образом. Ситуация и смысл соответствовал. Затем пришел нормальный ответ. остался в недоумении.

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

NULL можно представить как значение для представления неизвестного фрагмента данных (обратите внимание: не нулевого, хотя поле при этом выглядит пустым). А еще он не равен ничему, даже другому NULL. И сегодня мы поговорим об этом загадочном (на первый взгляд) значении NULL более подробно.

Пример значения NULL

Итак, что вы должны знать о значении NULL? Давайте разбираться.

Представьте себе письменный стол, на котором лежат канцелярские принадлежности: 6 шариковых ручек и 2 простых карандаша. Также известно, что в ящике стола должны быть фломастеры. Но вот сколько их и есть ли они вообще — данных нет. Если нам нужно составить таблицу инвентаризации с вводом значения NULL, то выглядеть она будет так:

InventoryID Item Количество
1 ручки 6
2 карандаши 2
3 фломастеры NULL

Значение NULL и НЕ NULL

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

select case when null is null then ‘YES’ else ‘NO’ end from dual; — YES

select case when ‘a’ is null then ‘YES’ else ‘NO’ end from dual; — NO

IS NOT NULL имеет обратный принцип: значение будет истинным, если операнд не является NULLом, и ложным, если он таковым является.

select case when ‘a’ is NOT null then ‘YES’ else ‘NO’ end from dual; — YES

select case when null is NOT null then ‘YES’ else ‘NO’ end from dual; — NO

Учтите, что когда речь идет об отсутствующих значениях, есть особые случаи их сравнения:

  • DECODE — принимает два NULLа за равные значения;
  • составные индексы — в случае, когда у двух ключей есть пустые поля, но заполненные поля при этом равны между собой, то Oracle воспримет эти ключи, как равные.

Как стать бэкенд-разработчиком: требования, пошаговая инструкция, полезные книги

Вот так проявляет себя DECODE:

select decode( null

, null, ‘EMPTY’ — это условие будет истинным

Значение NULL в MySQL

Результат при сравнении NULLов, в зависимости от операции SQL, часто будет иметь значение NULL. Предположим, что А НЕДЕЙСТВИТЕЛЕН:

Арифметические операторы

  • A + B = NULL
  • A – B = NULL
  • A * B = NULL
  • A/B = NULL

Ваш Путь в IT начинается здесь

Подробнее

  • A = B = NULL
  • A! = B = NULL
  • A> B = NULL
  • A!

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

Логические операции и NULL

Для логических операторов AND и OR есть свои особенности при работе со значением NULL. Краткое руководство рассмотрим на примере.

Как правило, НЕИЗВЕСТНО обрабатывается так же, как и состояние ЛОЖЬ. Если выбрать из таблицы строки и вычисление условия X=NULL в предложении WHERE дало результат НЕИЗВЕСТНО, то ни одной строки не будет получено. Но есть и различия: выражение НЕ(ЛОЖЬ) вернет истину, а НЕ(ИЗВЕСТНО) вернет НЕИЗВЕСТНО.

Чаще всего с неизвестным результатом работают как с ЛОЖЬЮ:

select 1 from dual where dummy = null; — запрос не вернёт записей

При отрицании неизвестности результатом будет НЕИЗВЕСТНО:

exec test_bool( not(null = null)); — UNKNOWN

exec test_bool( not(null != null) ); — UNKNOWN

exec test_bool( not(null = ‘a’) ); — UNKNOWN

exec test_bool( not(null != ‘a’) ); — UNKNOWN

exec test_bool(null or true); — TRUE кем хотите быть, когда вырастете?

Команда GeekBrains совместно с международными специалистами по развитию карьеры подготовили материалы, которые помогут вам начать путь к профессии мечты.

Скачивайте и используйте уже сегодня:

Александр Сагун

Топ-30 самых востребованных и высокооплачиваемых профессий 2022

Подборка 50+ ресурсов об IT-сфере

pdf иконка

3,7 MB

Операторы IN и NOT IN для значения NULL

Чтобы понять взаимодействие этих операторов с NULLом, рассмотрим пример.

Создадим таблицу Т, состоящую из одного числового столбца А и строками: 1, 2, 3 и NULL.

create table t as select column_value a from table(sys.odcinumberlist(1,2,3,null));

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

От трассировки в листингах оставлена часть filter, чтобы показать преобразование указанных в запросе условий.

set autotrace on

Теперь, после подготовительных действий, попробуем выбрать те записи, которые будут соответствовать набору (1, 2, NULL).

select * from t where a in(1,2,null); — вернёт [1,2]

select * from t where a in(1,2) or a is null; — вернёт [1,2,NULL]

Попробуем с NOT IN:

select * from t where a not in(1,2,null); — no rows selected

Ни одной записи так и не появилось.

Адаптивная верстка: задачи, преимущества и виды

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

Значение NULL и пустая строка в СУБД

Oracle отличается от стандартов ANSI SQL в определении NULLов: он проводит знак равенства между NULL и пустой строкой. Эта особенность программы рождает много споров, хотя Oracle и заявляет, что, возможно, в будущих релизах будет изменен подход в обработке пустой строки, как NULL. Но в реальности проведение таких изменений сомнительно, так как под эту СУБД написано неимоверное количество кода.

Александр Сагун

Мы вместе с экспертами по построению карьеры подготовили документы, которые помогут не ошибиться с выбором и определить, какая профессия в IT подходит именно вам.

Благодаря этим гайдам 76% наших студентов смогли найти востребованную профессию своей мечты!

Скоро мы уберем их из открытого доступа, успейте скачать бесплатно:

Гайд по профессиям в IT

5 профессий с данными о навыках и средней заработной плате

100 тыс. руб за 100 дней с новой профессией

Список из 6 востребованных профессий с заработком от 100 тыс. руб

Критические ошибки, которые могут разрушить карьеру

Собрали 7 типичных ошибок. Их нужно избегать каждому!

Женщины в IT: мифы и перспективы в карьере

Как делать хороший дизайн интерфейсов

Как прокачать свою технику речи

pdf иконка

4,7 MB

Если попытаться найти причину, почему вообще пустую строку стали считать эквивалентной NULL, то ответ можно найти в формате хранения varchar`ов и NULLов внутри блоков данных. Табличные строки Oracle хранит в структуре, представляющей собой заголовок и следующими за ним столбцы с данными.

Каждый столбец, в свою очередь, состоит из 2-х полей: длина данных в столбце (1 или 3 байта) и сами данные. При нулевой длине varchar2 в поле с данными нечего вносить, так как оно не занимает ни байта. В поле же, где указывается длина, вносится специальное значение 0xFF, что и означает отсутствие данных.

NULL Oracle представляет аналогично, то есть отсутствует поле с данными, а в поле длины данных вносится 0xFF. Так как изначально разработчики Oracle не разделяли эти два состояния, то и сейчас принцип внесения данных не изменился.

Значение NULL

Значение NULL

Неопределенная длина пустой строки:

Сравнение с пустой строкой невозможно:

Отличия между null и undefined

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

var element;

// значение переменной element до её инициализации не определённо: undefined

element = document.getElementById(‘not-exists’);

// здесь при попытке получения несуществующего элемента, метод getElementById возвращает null

// переменная element теперь инициализирована значением null, её значение определено

Осуществляя проверку на NULL или UNDEFINED, нужно помнить о разнице в операторах равенства (==) и идентичности (===): с первым оператором производится преобразование типов.

typeof undefined // undefined

null === undefined // false

null == undefined // true

Это все то, что вы должны знать о значении NULL. Обрастая опытом и применяя некоторые уловки для избежания NullPointerException, вы научитесь делать безопасный код. Главным образом неразбериха возникает из-за того, что NULL может трактоваться как пустое значение или как неидентифицированное.

Поэтому важно документально фиксировать поведение метода, когда есть входящее значение NULL. Держите в памяти, что NULL – это значение по умолчанию ссылочных переменных. И вызывать методы экземпляра или получать доступ к переменным экземпляра, применяя NULL-ссылку, вы не можете.

  1. Самое страшное: в качестве значения любого ссылочного типа может использоваться универсальный предатель — null, на которого никак не среагирует компилятор. Зато во время исполнения легко получить нож в спину — NullReferenceException. Обрабатывать это исключение бесполезно: оно означает безусловную ошибку в коде.
  2. Перец на рану: сбой (NRE при попытке разыменования) может находится очень далеко от дефекта (использование null там, где ждут полноценный объект).
  3. Упитанный пушной зверек: null неизлечим — никакие будущие нововведения в платформе и языке не избавят нас от прокаженного унаследованного кода, который физически невозможно перестать использовать.

Этот ящик Пандоры был открыт еще при создании языка ALGOL W великим Хоаром, который позднее назвал собственную идею ошибкой на миллиард долларов.

Разумеется, она была, причем очевидная по современным меркам

  1. Унифицированный Nullable для значимых и ссылочных типов.
  2. Разыменование Nullable только через специальные операторы (тернарный — ?:, Элвиса — ?., coalesce — ??), предусматривающие обязательную обработку обоих вариантов (наличие или отсутствие объекта) без выбрасывания исключений.
  3. Примеры:
  4. В этом случае NRE отсутствует по определению: возможность присвоить или передать null определяется типом значения, конвертация с выбросом исключения отсутствует.

Самое трагичное, что все это не было откровением и даже новинкой уже к моменту проектирования первой версии языка. Увы, тогда матерых функциональщиков в команде Хейлсберга не было.

Хотя прогноз очень серьезный, летального исхода можно избежать за счет применения различных практик и инструментов. Способы и их особенности пронумерованы для удобства ссылок.

Явные проверки на null в операторе if. Очень прямолинейный способ с массой серьезных недостатков.

  1. Гигантская масса шумового кода, единственное назначение которого — выбросить исключение поближе к месту предательства.
  2. Основной сценарий, загроможденный проверками, читается плохо
  3. Требуемую проверку легко пропустить или полениться написать
  4. Проверки можно добавлять отнюдь не везде (например, это нельзя сделать для автосвойств)
  5. Проверки не бесплатны во время выполнения.

Атрибут NotNull. Немного упрощает использование явных проверок

Паттерн проектирования Null object. Очень хороший способ, но с ограниченной сферой применения.

  1. Позволяет не использовать проверок на null там, где существует эквивалент нуля в виде объекта: пустой IEnumerable, пустой массив, пустая строка, ордер с нулевой суммой и т.п. Самое впечатляющее применение — автоматическая реализация интерфейсов в мок-библиотеках.
  2. Бесполезен в остальных ситуация: как только вам потребовалось отличать в коде нулевой объект от остальных — вы имеете эквивалент null вместо null object, что является уже двойным предательством: неполноценный объект, который даже NRE не выбрасывает.

Конвенция о возврате живых объектов по умолчанию. Очень просто и эффективно.

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

Конвенция о стандартных способах явно указать что свойство или метод может вернуть null: например, префикс Try или суффикс OrDefault в имени метода. Органичное дополнение к возврату полноценных объектов по умолчанию. Достоинства и недостатки те же.

Атрибут CanBeNull. Добрый антипод-близнец атрибута NotNull.

  1. Позволяют элегантно и лаконично организовать проверку и обработку null значений без потери прозрачности основного сценария обработки.
  2. Практически не упрощают выброс ArgumentException при передаче null в качестве значения NotNull параметра.
  3. Покрывают лишь некоторую часть вариантов использования.
  4. Остальные недостатки те же, что и у проверок в лоб.

Тип Optional. Позволяет явно поддержать отсутствие объекта.

  1. Можно полностью исключить NRE
  2. Можно гарантировать наличие обработки обоих основных вариантов на этапе компиляции.
  3. Против легаси этот вариант немного помогает, вернее, помогает немного.
  4. Во время исполнения помимо дополнительных инструкций добавляется еще и memory traffic

Монада Maybe. LINQ для удобной обработки случаев как наличия, так и отсутствия объекта.

  1. Сочетает элегантность кода с полнотой покрытия вариантов использования.
  2. В сочетании с типом Optional дает кумулятивный эффект.
  3. Отладка затруднена, так как с точки зрения отладчика вся цепочка вызовов является одной строкой.
  4. Легаси по-прежнему остается ахиллесовой пятой.
  1. В теории почти идеал, на практике все гораздо печальнее.
  2. Библиотека Code Contracts скорее мертва, чем жива.
  3. Очень сильное замедление сборки, вплоть до невозможности использовать в цикле редактирование-компиляция-отладка.

Пакет Fody/NullGuard. Автоматические проверки на null на стероидах.

  1. Проверяется все: передача параметров, запись, чтение и возврат значений, даже автосвойства.
  2. Никакого оверхеда в исходном коде
  3. Никаких случайных пропусков проверок
  4. Поддержка атрибута AllowNull — с одной стороны это очень хорошо, а с другой — аналогичный атрибут у решарпера другой.
  5. С библиотеками, агрессивно использующими null, требуется довольно много ручной работы по добавлению атрибутов AllowNull
  6. Поддержка отключения проверки для отдельных классов и целых сборок
  7. Используется вплетение кода после компиляции, но время сборки растет умеренно.
  8. Сами проверки работают только во время выполнения.
  9. Гарантируется выброс исключения максимально близко к дефекту (возврату null туда, где ожидается реальный объект).
  10. Тотальность проверок помогает даже при работе с легаси, позволяя как можно быстрее обнаружить, пометить и обезвредить даже null, полученный из чужого кода.
  11. Если отсутствие объекта допустимо — NullGuard сможет помочь только при попытках передать его куда не следует.
  12. Вычистив дефекты в тестовой версии, можно собрать промышленную из тех же исходников с отключенными проверками, получив нулевую стоимость во время выполнения при гарантии сохранения всей прочей логики.
  1. Проверки во время компиляции.
  2. Можно полностью ликвидировать NRE в новом коде.
  3. В реальности не реализовано, надеюсь, что только пока
  4. Единообразия со значимыми типами не будет.
  5. Легаси достанет и здесь.

Буду краток — все выводы в таблице:


Настоятельная рекомендация Антипаттерн На ваш вкус и потребности
4, 5, 7, 11, 12 (когда и если будет реализовано) 1, 2 3, 6, 8, 9, 10

На предвосхищение ООП через 20 лет не претендую, но дополнениям и критике буду очень рад.

Читайте также: