Tôi mong đợi điều này để làm việc, nhưng dường như cách IL tạo ra, nó ném NullReferenceException
. Tại sao trình biên dịch không thể tạo ra mã tương tự cho các truy vấn?C# 6 null toán tử điều kiện không hoạt động cho truy vấn LINQ
Trong trường hợp ThisWorks
, trình biên dịch tạo mã ngắn mạch phần còn lại của biểu thức, tại sao nó không thể làm điều tương tự cho trường hợp truy vấn 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
decompiled quả
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;
}
Tôi đoán là trình biên dịch dịch toán tử điều kiện null trước tiên trước khi dịch cú pháp truy vấn. Vì vậy, truy vấn của bạn giống như '(Child == null? Null: Child.Values) .Select (x => x)'. Nếu nó đã dịch cú pháp truy vấn sang cú pháp phương thức đầu tiên thì nó sẽ hoạt động. – juharr
Tại sao bạn mong đợi nó hoạt động khác? Trong ví dụ của bạn, 'target.Child? .Values' đánh giá thành' null'. Null có điều kiện chỉ ảnh hưởng đến biểu thức nó là một phần của. Bạn đang thực hiện một cách hiệu quả 'null.Select (...)'. –
@JeffMercado Tôi mong đợi 'từ x trong e? .Value chọn x' là' e? .Value.Select (x = x>) '* vì * biểu thức sau * hoạt động * đây là sự ngạc nhiên. Như @Neal đã chỉ ra, đó là khung giá tinh tế để đổ lỗi, cũng như thứ tự biến đổi quá –