2010-09-22 15 views
6

tôi đã tuyên bố như sau, mà luôn luôn trả về null:Tại sao Null là một phép chiếu LINQ không hợp lệ?

var addins = allocations.SelectMany(
     set => set.locations.Any(q => q.IsMatch(level, count)) 
     ? (List<string>)set.addins : null 
    ); 

tôi đã thay đổi nó một chút, và bây giờ nó hoạt động tốt:

var addins = allocations.SelectMany(
     set => set.locations.Any(q => q.IsMatch(level, count)) 
     ? set.addins : new List<string>() 
    ); 

câu hỏi chính của tôi: Tại sao có thể không phải là null đóng vai trò như một kiểu trả về từ toán tử bậc ba trong ngữ cảnh LINQ này?

Câu hỏi phụ: Có cách nào thông minh hơn để xây dựng truy vấn trên (đặc biệt nếu nó loại bỏ "Danh sách mới()")?

Trả lời

11

Enumerable.SelectMany sẽ cố gắng liệt kê trong chuỗi trả về bởi lambda của bạn, và nó ném một NullReferenceException cố gắng gọi GetEnumerator() trên null. Bạn cần cung cấp một chuỗi rỗng thực tế. Thay vì tạo ra một danh sách mới, bạn có thể sử dụng Enumerable.Empty:

var addins = allocations.SelectMany(
    set => set.locations.Any(q => q.IsMatch(level, count)) 
    ? (List<string>)set.addins : Enumerable.Empty<string>() 
    ); 

tôi nghi ngờ những gì bạn thực sự muốn là chỉ cần gọi đâu trước SelectMany để lọc ra các bộ bạn không muốn:

var addins = allocations 
    .Where(set => set.locations.Any(q => q.IsMatch(level, count))) 
    .SelectMany(set => (List<string>)set.addins); 

Hoặc, trong cú pháp truy vấn:

var addins = 
    from set in allocations 
    where set.locations.Any(q => q.IsMatch(level, count)) 
    from addin in (List<string>)set.addins 
    select addin; 
+1

Câu trả lời và thông tin chi tiết tuyệt vời Ngẫu nhiên, các diễn viên trên "set.addins" là không cần thiết trong các ví dụ khác của bạn, kể từ khi các nhà điều hành ternary không tham gia. –

1

Make rằng:

(List<string>)set.addins : (List<string>)null

+0

Tôi đã thử điều đó. Nó không thay đổi gì cả. :( –

Các vấn đề liên quan