Câu lệnh LINQ sau hoạt động như thế nào?
Đây là mã của tôi:
var list = new List<int>{1,2,4,5,6};
var even = list.Where(m => m%2 == 0);
list.Add(8);
foreach (var i in even)
{
Console.WriteLine(i);
}
Đầu ra: 2, 4, 6, 8
Tại sao không 2, 4, 6?
Câu lệnh LINQ sau hoạt động như thế nào?
Đây là mã của tôi:
var list = new List<int>{1,2,4,5,6};
var even = list.Where(m => m%2 == 0);
list.Add(8);
foreach (var i in even)
{
Console.WriteLine(i);
}
Đầu ra: 2, 4, 6, 8
Tại sao không 2, 4, 6?
Câu trả lời:
Đầu ra là 2,4,6,8do thực hiện hoãn lại .
Truy vấn được thực hiện khi biến truy vấn được lặp lại, không phải khi biến truy vấn được tạo. Điều này được gọi là thực hiện hoãn lại.
- Suprotim Agarwal, "Trì hoãn so với thực thi truy vấn ngay lập tức trong LINQ"
Có một thực thi khác gọi là Thực thi truy vấn tức thời , rất hữu ích cho kết quả truy vấn bộ đệm. Từ Suprotim Agarwal một lần nữa:
Để buộc thực thi ngay một truy vấn không tạo ra giá trị đơn lẻ, bạn có thể gọi phương thức
ToList(), ToDictionary(), ToArray(), Count(), Average()hoặcMax()phương thức trên một truy vấn hoặc biến truy vấn. Chúng được gọi là các toán tử chuyển đổi cho phép bạn tạo một bản sao / ảnh chụp kết quả và quyền truy cập nhiều lần bạn muốn mà không cần phải thực hiện lại truy vấn.
Nếu bạn muốn đầu ra là 2,4,6, sử dụng .ToList():
var list = new List<int>{1,2,4,5,6};
var even = list.Where(m => m%2 == 0).ToList();
list.Add(8);
foreach (var i in even)
{
Console.WriteLine(i);
}
.First(), .FirstOrDefault(), .Single()và .SingleOrDefault()cũng kích hoạt các đánh giá của truy vấn.
Điều này đã xảy ra do thực thi hoãn lại, có nghĩa là việc tính toán biểu thức không được thực hiện cho đến khi cần ở đâu đó. Điều này làm cho hiệu suất tốt hơn nếu dữ liệu quá lớn.
Lý do cho điều này là việc thực hiện hoãn biểu thức lambda của bạn. Truy vấn được thực thi khi bạn bắt đầu lặp trong vòng lặp foreach.
Bạn đang nhận được kết quả này vì thực thi bị trì hoãn có nghĩa là kết quả thực sự không được đánh giá cho đến khi truy cập lần đầu tiên.
Để làm cho nó rõ ràng hơn, chỉ cần thêm 10 vào danh sách ở cuối snipet của bạn và sau đó in lại, bạn sẽ không nhận được 10 trong đầu ra
var list = new List<int>{1,2,4,5,6};
var even = list.Where(m => m%2 == 0).Tolist();
list.Add(8);
foreach (var i in even)
{
Console.WriteLine(i);
}
//new*
list.Add(10);
foreach (var i in even)
{
Console.WriteLine(i);
}
10trong đầu ra.
8trong một trong hai đầu ra.