Linq Series 2- Biểu thức Lambda trong Linq
- Linq Series 8- Deferred Execution trong Linq querry
- Linq Series 7- Sử dụng IEnumerable và Method Chaining trong Linq
- Linq Series 6- Tìm hiểu về Fluent Interface và Method Chaining
- Linq Series 5- Phương thức mở rộng trong C# và ứng dụng trong Linq
- Linq Series 4- Một ví dụ cụ thể về ứng dụng lambda expression trong Linq
Table of Contents
Biểu thức Lambda trong Linq
Xin chào các bạn, trong bài trước chúng ta đã tìm hiểu về khái niệm linq trong c# , lợi ích của việc sử dụng linq và linq api gồm 2 lớp là Enumerable và Querryable, 2 cách có thể viết querry trong linq : Cú pháp truy vấn trong linq, cú pháp phương thức trong linq. Hôm nay mình xin giới thiệu về biểu thức lambda trong linq – thành phần cấu tạo của linq querry hay lamda expression .
Tìm hiểu về biểu thức Lambda
C# 3.0 (.NET Framework 3.5) đã giới thiệu biểu thức lambda cùng với LINQ. Biểu thức lambda là một cách ngắn hơn để biểu diễn phương thức ẩn danh bằng cách sử dụng một số cú pháp đặc biệt.
Ví dụ: phương thức ẩn danh sau kiểm tra nếu sinh viên là thiếu niên hay không (độ tuổi từ 13 đến 19):
delegate(Student s) { return s.Age > 12 && s.Age < 20; };
Phương thức ẩn danh ở trên có thể được biểu diễn bằng biểu thức Lambda trong C# như sau:
s => s.Age > 12 && s.Age < 20
Chúng ta hãy xem cách biểu thức lambda tiến hóa từ phương thức ẩn danh sau:
delegate(Student s) { return s.Age > 12 && s.Age < 20; };
Biểu thức Lambda tiến hóa từ phương thức ẩn danh bằng cách loại bỏ từ khóa delegate và kiểu dữ liệu của tham số rồi thêm toán tử lambda =>
.
Biểu thức lambda ở trên là hoàn toàn hợp lệ, nhưng chúng ta không cần dấu ngoặc nhọn, return và dấu chấm phẩy nếu chúng ta chỉ có một câu lệnh trả về giá trị. Vì vậy, chúng ta có thể loại bỏ nó.
Ngoài ra, chúng ta có thể loại bỏ dấu ngoặc đơn (), nếu chúng ta chỉ có một tham số.
Do đó, chúng ta có biểu thức lambda: s => s.Age > 12 && s.Age < 20
trong đó s
là một tham số, =>
là toán tử lambda và s.Age > 12 && s.Age < 20
là thân của biểu thức:
Biểu thức Lambda với nhiều tham số
Bạn có thể đóng gói các tham số trong ngoặc đơn nếu bạn cần truyền nhiều hơn một tham số như sau:
(s, youngAge) => s.Age > youngage;
Bạn cũng có thể đưa ra kiểu dữ liệu của từng tham số nếu tham số gây nhầm lẫn như sau:
(Student s,int youngAge) => s.Age > youngage;
Biểu thức Lambda không có tham số
Không nhất thiết phải có ít nhất một tham số trong biểu thức lambda. Biểu thức lambda có thể được chỉ định mà không có bất kỳ tham số nào như ví dụ dưới đây:
() => Console.WriteLine("Parameter less lambda expression")
Nhiều câu lệnh trong thân của biểu thức Lambda
Bạn có thể đóng gói biểu thức trong dấu ngoặc nhọn nếu bạn muốn có nhiều hơn một câu lệnh trong thân của biểu thức Lambda như ví dụ dưới đây:
(s, youngAge) =>
{
Console.WriteLine("Lambda expression with multiple statements in the body");
return s.Age > youngAge;
}
Khai báo biến cục bộ trong thân của biểu thức Lambda
Bạn có thể khai báo biến trong thân của biểu thức Lambda để sử dụng nó ở bất cứ đâu trong thân của biểu thức như sau:
s =>
{
int youngAge = 18;
Console.WriteLine("Lambda expression with multiple statements in the body");
return s.Age > youngAge;
}
Biểu thức Lambda cũng có thể được chỉ định cho các delegate tích hợp như Func , Action và Predicate .
Chỉ định biểu thức Lambda cho delegate
Delegate Func
Biểu thức lambda có thể được chỉ định để delegate kiểu Func<in T, out TResult>
. Kiểu tham số cuối cùng trong một delegate Func
là kiểu trả về và phần còn lại là các tham số đầu vào. Truy cập bài viết về delegate Func trong lập trình C# để biết thêm về nó.
Ví dụ: biểu thức lambda sau đây được dùng để kiểm tra xem một học sinh có phải là một thiếu niên hay không (tuổi từ 13 – 19):
Func<Student, bool> isStudentTeenAger = s => s.Age > 12 && s.Age < 20;
Student std = new Student() { Age = 21 };
bool isTeen = isStudentTeenAger(std);// returns false
Trong ví dụ trên, delegate Func yêu cầu tham số đầu vào đầu tiên là kiểu Student và kiểu trả về là boolean. Biểu thức lambda s => s.age > 12 && s.age < 20
thỏa mãn yêu cầu của delegate Func<Student, bool>, như được trình bày ở hình bên dưới:
Delegate Func được trình bày ở trên hóa ra là một chức năng như được trình bày ở ví dụ bên dưới.
bool isStudentTeenAger(Student s)
{
return s.Age > 12 && s.Age < 20;
}
Delegate Action
Không giống như delegate Func, delegate Action chỉ có các tham số đầu vào. Sử dụng kiểu delegate Action khi bạn không cần trả về bất kỳ giá trị nào từ biểu thức lambda.
Action<Student> PrintStudentDetail = s =>
Console.WriteLine($"Name: {s.StudentName}, Age: {s.Age}");
Student std = new Student()
{
StudentName = "Bill",
Age = 21
};
PrintStudentDetail(std);//output: Name: Bill, Age: 21
Delegate Predicate
Không giống như delegate Action, delegate Predicate có các tham số đầu vào và luôn trả về kiểu boolean (có thể xem delegate Predicate là một delegate Func<in T, out bool>). Sử dụng kiểu delegate Predicate khi bạn cần trả về giá trị kiểu bool từ biểu thức lambda.
Predicate<Student> isStudentTeenAger = s => s.Age > 12 && s.Age < 20;
Student std = new Student() { Age = 18 };
bool isTeen = isStudentTeenAger(std);// returns true
Biểu thức Lambda trong truy vấn LINQ
Thông thường biểu thức lambda được sử dụng với truy vấn LINQ. Lớp tĩnh Enumerable bao gồm phương thức mở rộng Where
cho các lớp triển khai interface IEnumerable<T>
chấp nhận tham số delegate Func<TSource,bool>
.
Vì vậy, phương thức mở rộng Where
cho danh sách IEnumerable<Student>
được yêu cầu phải truyền tham số Func<Student,bool>
, như được hiển thị ở hình bên dưới:
Biểu thức Lambda trong truy vấn LINQ
Vì vậy, bây giờ bạn có thể truyền biểu thức lambda cho phương thức mở rộng Where
trong cú pháp phương thức truy vấn LINQ như dưới đây:
IList<Student> studentList = new List<Student>(){...};
var teenStudents = studentList
.Where(s => s.age > 12 && s.age < 20)
.ToList<Student>();
Những điểm cần nhớ về biểu thức lambda
- Biểu thức Lambda là một cách ngắn hơn để biểu diễn phương thức ẩn danh.
- Cú pháp biểu thức Lambda:
parameters => body expression
- Biểu thức Lambda có thể không có tham số.
- Biểu thức Lambda có thể có nhiều tham số đặt trong cặp dấu ngoặc đơn ().
- Biểu thức Lambda có thể có nhiều câu lệnh trong thân của biểu thức đặt trong cặp dấu ngoặc nhọn {}.
- Biểu thức Lambda có thể được gán cho delegate Func, Action hoặc Prateate.
- Biểu thức Lambda có thể được gọi theo cách tương tự như delegate.
Học viên Phạm Tuấn Vũ
Bình luận (0
)