С# 6 null условный оператор не работает для запроса LINQ
Я ожидал, что это сработает, но, по-видимому, так, как генерирует ИЛ, он бросает NullReferenceException
. Почему компилятор не может генерировать аналогичный код для запросов?
В случае ThisWorks
компилятор генерирует код, который замыкает оставшуюся часть выражения, почему он не может сделать то же самое для случая запроса LINQ?
class Target
{
public ChildTarget Child;
}
class ChildTarget
{
public int[] Values;
}
IEnumerable<int> ThisWorks(Target target) =>
target.Child?.Values.Select(x => x);
IEnumerable<int> ThisDoesNotWork(Target target) =>
from x in target.Child?.Values select x;
ThisWorks(new Target());
ThisDoesNotWork(new Target()); // this throws NullReferenceException
Декомпилированные результаты
private static IEnumerable<int> ThisDoesNotWork(Target target)
{
ChildTarget child = target.Child;
IEnumerable<int> values = (child != null) ? child.Values : null;
Func<int, int> func;
if ((func = Program._func) == null)
{
func = (Program._func = new Func<int, int>(Program._funcMethod));
}
return values.Select(func);
}
private static IEnumerable<int> ThisWorks(Target target)
{
ChildTarget child = target.Child;
IEnumerable<int> values;
if (child == null)
{
values = null;
}
else
{
IEnumerable<int> values = child.Values;
Func<int, int> func;
if ((func = Program._func2) == null)
{
func = (Program._func2= new Func<int, int>(Program._funcMethod2));
}
values = values.Select(func);
}
return values;
}
Ответы
Ответ 1
Ответ указан в спецификации языка С#, в которой говорится
Выражение запроса формы
из x в e выберите x
переводится в
(e). Выберите (x = > x)
Обратите внимание на круглые скобки вокруг e в последней строке. Это ясно показывает, что выражение с нулевым условием (в вашем примере) заканчивается до вызова Select, что означает, что Select может быть вызван с результатом null.
Почему он не может сделать то же самое для Linq? Потому что это не то, как функция была разработана для работы. Спецификация для операторов с нулевым условием не имеет специального случая для запросов, и наоборот.