Использование Null Conditional Operator для проверки значений объектов, которые могут быть нулевыми

Я играл с С# 6 Null Conditional Operator (подробнее здесь).

Мне очень нравится синтаксис, и я думаю, что он делает код более читаемым, но я думаю, что сомнительно, что именно код будет делать, когда вы столкнетесь с проверкой значения свойства на объекте, который сам может be null.

Например, если у меня был класс с десятичным свойством на нем, и мне нужна условная проверка значения этого десятичного числа, я бы написал что-то вроде:

if (foo?.Bar > max)
{
   // do something
}

На поверхности это выглядит великолепно... Если foo не является нулевым, получите значение Bar и проверьте, превышает ли оно максимальное значение, если оно есть, что-то делать.

Однако, если foo имеет значение null?!

В этой документации о новых и улучшенных функциях С# 6 говорится следующее:

если на самом деле значение объекта равно null, нулевое условие оператор вернет null. Он замыкает вызов в Bar, и немедленно возвращает null, избегая ошибки программирования, которая в противном случае возникает исключение NullReferenceException.

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

Как короткое замыкание равно false? В моей голове этот код теперь скажет: "Если foo имеет значение null, проверьте, является ли null значением max, что невозможно, поэтому верните false" или "Если foo имеет значение null, то foo!= Null вернет false, так что вы получите false", однако в документации указано, что нулевая условная проверка возвращает значение null, а не false.

Ответ 1

Как короткое замыкание равно false?

if (foo?.Bar > max)
{
   // do something
}

примерно эквивалентно:

Decimal? bar = null;
if (foo != null)
    bar = foo.Bar;

if (bar > max)
{
   // do something
}

Таким образом, короткое замыкание не равно false. Он равен Decimal? (nullable Decimal), который , а затем по сравнению с max.

См. также: Как работает оператор сравнения с нулевым int?

Ответ 2

Он замыкает вызов на бар

означает остановить проверку следующих шагов (.) в цепочке ссылок объектов, если родительский объект уже имеет значение null. Это означает, что операторы, подобные сравнению, не влияют, потому что вы используете значение вместо перемещения в цепочке. Это поведение называется нулевым распространением. Вы можете найти интересные описания в Code Project или Dave Fancher.

Использование оператора null null возвращает значение с нулевым значением, например double?. Затем это значение сравнивается с max. Поведение нуля в таком сравнении хорошо описывается Microsoft:

Когда вы выполняете сравнения с типами NULL, если значение одного нулевых типов - null, а другой - нет, все сравнения оценивать значение false, за исключением if = (не равно).

Это означает:

if (null > max)
{
    //never called
}

Ответ 3

Null Conditional Operator следует использовать только для сценариев, связанных с свойствами объектов, с несколькими присваиваниями (см. сопоставление объектов и т.д.), где это может быть скучно проверять каждый раз, если возникает нулевое условие свойства.

Или также для сценариев, как показано ниже:

int? count = customers?[0]?.Orders?.Count();  // null if customers, the first customer, or Orders is null 

Используя этот оператор в тестовом выражении if, это может привести к неожиданному поведению, например, в вашем случае if case on fiddler вы получаете "пройденный" тест (последний if), но с null значением, которое, очевидно, не является допустимым случаем