2012-06-19 30 views
6

Tôi đã thử nghiệm với LINQ để xem những gì nó có thể làm - và tôi thực sự yêu thích nó cho đến nay :)Thực hiện trì hoãn LINQ với giá trị địa phương

Tôi đã viết một số truy vấn cho một thuật toán, nhưng tôi đã không t có được kết quả mong đợi của tôi ... các Enumeration luôn được trả về rỗng:

trường hợp # 1

List<some_object> next = new List<some_object>(); 
some_object current = null; 

var valid_next_links = 
    from candidate in next 
    where (current.toTime + TimeSpan.FromMinutes(5) <= candidate.fromTime) 
    orderby candidate.fromTime 
    select candidate; 

current = something; 
next = some_list_of_things; 

foreach (some_object l in valid_next_links) 
{ 
    //do stuff with l 
} 

tôi đã thay đổi tờ khai truy vấn là inline như thế này, và nó làm việc tốt:

trường hợp # 2

foreach (some_object l in 
     (from candidate in next 
     where (current.toTime + TimeSpan.FromMinutes(5) <= candidate.fromTime) 
     orderby candidate.fromTime 
     select candidate)) 
{ 
    //do stuff with l 
} 

Có ai biết tại sao nó không hoạt động trong trường hợp # 1? Cách tôi hiểu nó, truy vấn không được đánh giá khi bạn tuyên bố nó, vì vậy tôi không thấy làm thế nào có sự khác biệt.

Trả lời

7

Thay đổi thành current sẽ bị bắt nhưng truy vấn đã biết giá trị của next. Việc thêm các mục bổ sung vào danh sách hiện có sẽ làm cho chúng hiển thị trong truy vấn, nhưng việc thay đổi giá trị của biến để tham chiếu đến một danh sách khác hoàn toàn sẽ không có bất kỳ ảnh hưởng nào. Về cơ bản, nếu bạn mở rộng truy vấn từ biểu thức truy vấn thành biểu mẫu "bình thường", bất kỳ biến nào có trong biểu thức lambda sẽ được ghi dưới dạng biến, nhưng bất kỳ biến nào hiện diện trực tiếp dưới dạng đối số sẽ được đánh giá ngay lập tức. Điều đó sẽ chỉ ghi lại giá trị tham chiếu của biến, chứ không phải các mục có trong danh sách, nhưng nó vẫn có nghĩa là việc thay đổi giá trị biến sẽ không được nhìn thấy. Truy vấn đầu tiên của bạn mở rộng tới:

var valid_next_links = next 
     .Where(candidate => (current.toTime + TimeSpan.FromMinutes(5) <= candidate.fromTime)) 
     .OrderBy(candidate => candidate.fromTime); 
Các vấn đề liên quan