Почему я могу опустить последующие нуль-условные операторы в цепочке вызовов?
Рассмотрим следующий код:
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
,