Нулевой оператор

var a = b?.cd;

Разве это выражение не должно всегда давать ошибку компиляции? Если b равно нулю, значение null распространяется через, поэтому c также будет равно нулю и, следовательно, также нуждается в этом операторе. В моем понимании использование этого оператора в выражении распространяется вирусно.

Но ни Visual Studio 2015, ни Resharper мне ничего не говорят, я что-то здесь упускаю?

4 ответа

Решение

Оператор просто синтаксический сахар для этого:

MyType a = b == null ? 
    null: 
    b.c.d;

Почему это должно привести к ошибке компиляции, мне неясно.

Если b равно нулю, значение null распространяется через, поэтому c также будет равно нулю и, следовательно, также потребуется этот оператор

Это не правда На самом деле, когда b нулевой c даже не существует, так как нет экземпляра, на котором этот член мог бы существовать. Короче оператор просто возвращается null и опускает оценку c или даже d дальше

Этот оператор делает короткое замыкание и возвращает null в случае b является null,

var a = b == null ? null : b.c.d

Вот как это утверждение выглядело бы по-старому: ?. Оператор не смотрит глубже, когда то, что находится до того, как он становится нулевым, он просто возвращает ноль, однако вы получите ошибку, где b определяется, но b.c == null так как ты не писал как var a = b?.c?.d,

Обратите внимание, что:

var a1 = b?.c.d;

полностью отличается от:

var a2 = (b?.c).d;

Не очень легко объяснить вкратце, как унарный оператор ?. работает (да, одинарный!). Но идея в том, что остальная часть "цепочки" "операций" пропускается, если выражение до ?. нулевой.

Таким образом, для a1, вы получаете нуль типа времени компиляции, переносимого членом d (или же Nullable<> такого типа, если это необходимо) всякий раз, когда b бывает нулевым. когда b бывает ненулевым, вы получаете то же самое, что и b.c.d который может потерпеть неудачу, если b.c нулевой.

Но a2 совсем другое. Это всегда взорвется, если b является нулевым, потому что тогда скобка (b?.c) будет нулевой ссылкой, а следующий . оператор приведет к NullReferenceException, (Я предполагаю, что здесь c имеет тип ссылки во время компиляции.)

Так что не думайте, что существует какая-то "левая ассоциативность", которая делает b?.c.d эквивалентно (b?.c).d!


Вы можете найти ссылку на предварительную Спецификацию языка C# в этом ответе в другой ветке; в качестве унарного оператора они упоминают нуль-условный оператор в § 7.7.1.

Другие вопросы по тегам