IEnumerable<T>
đại diện cho một con trỏ chỉ về phía trước của T
. .NET 3.5 đã thêm các phương thức mở rộng bao gồm LINQ standard query operators
tương tự Where
và First
, với bất kỳ toán tử nào yêu cầu các biến vị ngữ hoặc hàm ẩn danh Func<T>
.
IQueryable<T>
thực hiện cùng các toán tử truy vấn tiêu chuẩn LINQ, nhưng chấp nhận Expression<Func<T>>
các biến vị ngữ và hàm ẩn danh. Expression<T>
là một cây biểu thức được biên dịch, một phiên bản chia nhỏ của phương thức ("được biên dịch một nửa" nếu bạn muốn) có thể được phân tích cú pháp bởi nhà cung cấp truy vấn và được sử dụng theo đó.
Ví dụ:
IEnumerable<Person> people = GetEnumerablePeople();
Person person = people.Where(x => x.Age > 18).FirstOrDefault();
IQueryable<Person> people = GetQueryablePeople();
Person person = people.Where(x => x.Age > 18).FirstOrDefault();
Trong khối đầu tiên, x => x.Age > 18
là một phương thức ẩn danh ( Func<Person, bool>
), có thể được thực thi như bất kỳ phương thức nào khác. Enumerable.Where
sẽ thực thi phương thức một lần cho mỗi người, lấy yield
các giá trị mà phương thức trả về true
.
Trong khối thứ hai, x => x.Age > 18
là một cây biểu thức ( Expression<Func<Person, bool>>
), có thể được coi là "là thuộc tính 'Tuổi'> 18".
Điều này cho phép những thứ như LINQ-to-SQL tồn tại bởi vì chúng có thể phân tích cây biểu thức và chuyển đổi nó thành SQL tương đương. Và bởi vì nhà cung cấp không cần thực thi cho đến khi IQueryable
được liệt kê (rốt cuộc, nó thực hiện IEnumerable<T>
), nên nó có thể kết hợp nhiều toán tử truy vấn (trong ví dụ trên Where
và FirstOrDefault
) để đưa ra các lựa chọn thông minh hơn về cách thực hiện toàn bộ truy vấn đối với dữ liệu cơ bản nguồn (như sử dụng SELECT TOP 1
trong SQL).
Xem: