Nói theo chức năng, LINQ không là gì ngoài việc đơn giản hóa cú pháp thể hiện các đơn nguyên. LINQ to Objects (List-comprehensions - thậm chí điều này đã vô cùng hữu ích), mà bạn đã nói đến, chỉ là một ứng dụng có thể này (tương tự như List-Monad trong Haskell).
Nếu bạn viết
from x in expr1
from y in expr2
select x + y
nó không có gì nhưng
do
x <- expr1
y <- expr2
return $ x + y
trong Haskell.
Điều cụ thể được thực hiện tùy thuộc vào người dùng được xác định Nhà cung cấp LINQ (Extension-Methods) trong đó Linq.Enumerable
chỉ là một triển khai liên quan đến IEnumerable
s.
Bằng cách cung cấp một, bạn có thể tạo LINQ ngữ nghĩa hoàn toàn mới cho các loại của mình.
Ví dụ: Đưa ra loại Option
cho các tính toán có thể thất bại (giá trị nullable), người ta có thể xác định nhà cung cấp LINQ để truy vấn trên chúng.
public static class MaybeExtensions
{
public static Option<T> ToMaybe<T>(this T value)
{
return Option<T>.Some(value);
}
public static Option<U> SelectMany<T, U>(
this Option<T> m,
Func<T, Option<U>> k)
{
return !m.IsNone ? Option<U>.None : k(m.Value);
}
public static Option<V> SelectMany<T, U, V>(
this Option<T> m,
Func<T, Option<U>> k,
Func<T, U, V> s)
{
return m.SelectMany(x => k(x).SelectMany(y => s(x, y).ToMaybe()));
}
}
này bây giờ sẽ cho phép chúng ta viết mã như:
var sum = from x in ReadNumber("x")
from y in ReadNumber("y")
select x + y;
Việc tính toán sẽ chỉ trả lại một giá trị nếu tất cả các tính toán thành công và nếu không sẽ thất bại ở lần đầu tiên thất bại trong một.
Kết hợp với cây biểu thức, LINQ có thể cực kỳ mạnh mẽ và cho phép bạn thể hiện -
- Cơ sở dữ liệu truy cập
- Asynchronous programm dòng
- lẽ-Monads
- Danh sách comprehensions
- Recursive trình phân tích cú pháp gốc
- Continuations
- Mini-ngôn ngữ
- tính toán song song (PLINQ)
Một số liên kết:
Kết hợp với bộ phối hợp điểm cố định, LINQ cung cấp đầy đủ chức năng nhỏ ngôn ngữ (Linq raytracer).
Lưu ý rằng Scala và F # Cả hai đều có những khái niệm tương tự trong cho-comprehensions và các biểu thức tính toán cả hai là trừu tượng monadic:
Scala:
for (x <- expr1
y <- expr2) yield x + y
F #:
monad {
let! x = expr1
let! y = expr2
return x + y
}
Cảm ơn bạn đã thông tin. Tôi sẽ nhìn vào những người dẫn đầu. – Joe
Thực sự, tóm tắt thực sự tốt với một ví dụ tốt đẹp, dễ nắm bắt. +1 –
Tiếp tục liên kết raytracer, đây là cùng một raytracer được triển khai hoàn toàn trong một câu lệnh LINQ: http://tirania.org/blog/archive/2007/Nov-16.html – JulianR