Почему я могу опустить последующие нуль-условные операторы в цепочке вызовов?

Рассмотрим следующий код:

IEnumerable<int> xx = null;
var tt = xx?.Where(x => x > 2).Select(x => x.ToString());

Назначает null в tt, Вопрос в том, почему он работает правильно?

Я думал, что я должен использовать ?. прежде чем выбрать как ?.Where(...) возвращается null, Кроме того, если я разделю вторую строку на две отдельные строки:

IEnumerable<int> xx = null;
var yy = xx?.Where(x => x > 2);
var zz = yy.Select(x => x.ToString());

Там будет ArgumentNullException на третьей строке как yy == null,

Что за магия?:)
Если это из-за короткого замыкания, я никогда не думал, что это может действовать так.

2 ответа

Решение

Да, это связано с коротким замыканием. Из ссылки на MSDN:

... [T] операторы с нулевым условием имеют короткое замыкание. Если одна операция в цепочке условного доступа к элементу и операции с индексом возвращает ноль, то выполнение остальной части цепочки прекращается.

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

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

var tt = xx?.Where(x => x > 2).Select(x => x.ToString());

возвращается null, затем выполнение остальной части цепочки останавливается.

Так в приведенном выше примере Where никогда не вызывается как xx является null,

Что касается второго примера, вы получаете ArgumentNullExceptionпотому что это поведение методов расширения. в этом конкретном случае Select бросает ArgumentNullException когда источник или предоставленный селектор null,

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