LINQ - Biểu thức Lambda
Thuật ngữ 'biểu thức Lambda' bắt nguồn từ tên của nó từ phép tính 'lambda', đến lượt nó là một ký hiệu toán học được áp dụng để xác định các hàm. Biểu thức Lambda như một phần thực thi của phương trình LINQ dịch logic theo một cách tại thời điểm chạy để nó có thể chuyển đến nguồn dữ liệu một cách thuận tiện. Tuy nhiên, các biểu thức lambda không chỉ giới hạn để tìm ứng dụng trong LINQ.
Các biểu thức này được thể hiện bằng cú pháp sau:
(Input parameters) ⇒ Expression or statement block
Đây là một ví dụ về biểu thức lambda -
y ⇒ y * y
Biểu thức trên chỉ định một tham số có tên là y và giá trị đó của y là bình phương. Tuy nhiên, không thể thực thi biểu thức lambda ở dạng này. Ví dụ về biểu thức lambda trong C # được hiển thị bên dưới.
C #
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace lambdaexample {
class Program {
delegate int del(int i);
static void Main(string[] args) {
del myDelegate = y ⇒ y * y;
int j = myDelegate(5);
Console.WriteLine(j);
Console.ReadLine();
}
}
}
VB
Module Module1
Private Delegate Function del(ByVal i As Integer) As Integer
Sub Main(ByVal args As String())
Dim myDelegate As del = Function(y) y * y
Dim j As Integer = myDelegate(5)
Console.WriteLine(j)
Console.ReadLine()
End Sub
End Module
Khi đoạn mã trên của C # hoặc VB được biên dịch và thực thi, nó tạo ra kết quả sau:
25
Biểu thức Lambda
Vì biểu thức trong cú pháp của biểu thức lambda được hiển thị ở trên nằm ở phía bên tay phải, chúng còn được gọi là biểu thức lambda.
Async Lambdas
Biểu thức lambda được tạo bằng cách kết hợp xử lý không đồng bộ bằng cách sử dụng từ khóa async được gọi là lambdas không đồng bộ. Dưới đây là một ví dụ về lambda không đồng bộ.
Func<Task<string>> getWordAsync = async()⇒ “hello”;
Lambda trong toán tử truy vấn chuẩn
Một biểu thức lambda trong toán tử truy vấn được đánh giá giống nhau theo yêu cầu và liên tục hoạt động trên từng phần tử trong chuỗi đầu vào chứ không phải toàn bộ chuỗi. Các nhà phát triển được biểu thức Lambda cho phép cung cấp logic của riêng họ vào các toán tử truy vấn tiêu chuẩn. Trong ví dụ dưới đây, nhà phát triển đã sử dụng toán tử 'Where' để lấy lại các giá trị lẻ từ danh sách đã cho bằng cách sử dụng biểu thức lambda.
C #
//Get the average of the odd Fibonacci numbers in the series...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace lambdaexample {
class Program {
static void Main(string[] args) {
int[] fibNum = { 1, 1, 2, 3, 5, 8, 13, 21, 34 };
double averageValue = fibNum.Where(num ⇒ num % 2 == 1).Average();
Console.WriteLine(averageValue);
Console.ReadLine();
}
}
}
VB
Module Module1
Sub Main()
Dim fibNum As Integer() = {1, 1, 2, 3, 5, 8, 13, 21, 34}
Dim averageValue As Double = fibNum.Where(Function(num) num Mod 2 = 1).Average()
Console.WriteLine(averageValue)
Console.ReadLine()
End Sub
End Module
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
7.33333333333333
Nhập Suy luận bằng Lambda
Trong C #, kiểu suy luận được sử dụng thuận tiện trong nhiều trường hợp khác nhau và cũng như vậy mà không cần chỉ định kiểu rõ ràng. Tuy nhiên trong trường hợp biểu thức lambda, suy luận kiểu sẽ chỉ hoạt động khi mỗi kiểu đã được chỉ định vì trình biên dịch phải được thỏa mãn. Hãy xem xét ví dụ sau đây.
delegate int Transformer (int i);
Ở đây trình biên dịch sử dụng kiểu suy luận để dựa trên thực tế rằng x là một số nguyên và điều này được thực hiện bằng cách kiểm tra kiểu tham số của Transformer.
Phạm vi biến trong biểu thức Lambda
Có một số quy tắc trong khi sử dụng phạm vi biến trong biểu thức lambda như các biến được khởi tạo trong biểu thức lambda không có nghĩa là hiển thị trong một phương thức bên ngoài. Cũng có một quy tắc rằng một biến được capture không được thu gom trừ khi đại biểu tham chiếu đến biến đó đủ điều kiện để thực hiện hành động thu gom rác. Hơn nữa, có một quy tắc cấm một câu lệnh trả về trong một biểu thức lambda để gây ra việc trả về một phương thức bao.
Đây là một ví dụ để chứng minh phạm vi biến trong biểu thức lambda.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace lambdaexample {
class Program {
delegate bool D();
delegate bool D2(int i);
class Test {
D del;
D2 del2;
public void TestMethod(int input) {
int j = 0;
// Initialize the delegates with lambda expressions.
// Note access to 2 outer variables.
// del will be invoked within this method.
del = () ⇒ { j = 10; return j > input; };
// del2 will be invoked after TestMethod goes out of scope.
del2 = (x) ⇒ { return x == j; };
// Demonstrate value of j:
// The delegate has not been invoked yet.
Console.WriteLine("j = {0}", j); // Invoke the delegate.
bool boolResult = del();
Console.WriteLine("j = {0}. b = {1}", j, boolResult);
}
static void Main() {
Test test = new Test();
test.TestMethod(5);
// Prove that del2 still has a copy of
// local variable j from TestMethod.
bool result = test.del2(10);
Console.WriteLine(result);
Console.ReadKey();
}
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
j = 0
j = 10. b = True
True
Cây biểu hiện
Biểu thức lambda được sử dụng trong Expression Treexây dựng rộng rãi. Một cây biểu thức cung cấp mã trong một cấu trúc dữ liệu giống như một cây trong đó mỗi nút tự nó là một biểu thức giống như một lệnh gọi phương thức hoặc có thể là một phép toán nhị phân như x <y. Dưới đây là một ví dụ về cách sử dụng biểu thức lambda để xây dựng một cây biểu thức.
Tuyên bố Lambda
Ngoài ra còn có statement lambdasbao gồm hai hoặc ba câu lệnh, nhưng không được sử dụng trong việc xây dựng cây biểu thức. Một câu lệnh trả về phải được viết trong một câu lệnh lambda.
Cú pháp của câu lệnh lambda
(params)⇒ {statements}
Ví dụ về câu lệnh lambda
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
namespace lambdaexample {
class Program {
static void Main(string[] args) {
int[] source = new[] { 3, 8, 4, 6, 1, 7, 9, 2, 4, 8 };
foreach (int i in source.Where(x ⇒
{
if (x <= 3)
return true;
else if (x >= 7)
return true;
return false;
}
))
Console.WriteLine(i);
Console.ReadLine();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
3
8
1
7
9
2
8
Lambdas được sử dụng làm đối số trong các truy vấn LINQ dựa trên các phương thức và không bao giờ được phép có một vị trí ở phía bên trái của các toán tử như is hoặc là asgiống như các phương pháp ẩn danh. Mặc dù, các biểu thức Lambda rất giống các phương thức ẩn danh, nhưng chúng không bị hạn chế chỉ được sử dụng làm đại biểu.
Những điểm cần nhớ khi sử dụng biểu thức lambda
Một biểu thức lambda có thể trả về một giá trị và có thể có các tham số.
Các tham số có thể được định nghĩa theo vô số cách với biểu thức lambda.
Nếu có một câu lệnh duy nhất trong một biểu thức lambda, thì không cần dấu ngoặc nhọn trong khi nếu có nhiều câu lệnh, thì dấu ngoặc nhọn cũng như giá trị trả về là điều cần thiết để viết.
Với biểu thức lambda, có thể truy cập các biến có mặt bên ngoài khối biểu thức lambda bằng một tính năng được gọi là bao đóng. Việc sử dụng đóng cửa nên được thực hiện một cách thận trọng để tránh bất kỳ vấn đề nào.
Không thể thực thi bất kỳ mã không an toàn nào bên trong bất kỳ biểu thức lambda nào.
Biểu thức Lambda không được sử dụng ở phía bên trái của toán tử.