Ngôn ngữ LINQ - Toán tử where

Toán tử lọc Where trong LINQ

Toán tử Where (một phương thức mở rộng của LINQ) lọc danh sách dựa trên biểu thức điều kiện đã cho và trả về danh sách mới. Các điều kiện có thể là biểu thức lambda hoặc delegate Func.

Phương thức mở rộng Where sau có hai phương thức quá tải. Cả hai phương thức quá tải đều chấp nhận tham số kiểu delegate Func.

Phương thức quá tải đầu tiên yêu cầu tham số đầu vào là Func<TSource, bool> và phương thức quá tải thứ hai yêu cầu tham số đầu vào Func<TSource, int, bool> trong đó int là chỉ mục:

// first
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);
// second
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, int, bool> predicate);

Mệnh đề where trong cú pháp truy vấn LINQ

Mẫu truy vấn sau đây sử dụng toán tử Where để lọc các học sinh tuổi teen (từ 13 - 19 tuổi) từ danh sách học sinh đã cho. Nó sử dụng biểu thức lambda như một hàm vị ngữ.

// Student collection
IList<Student> studentList = new List<Student>() 
{ 
	new Student() { StudentID = 1, StudentName = "John", Age = 13 },
	new Student() { StudentID = 2, StudentName = "Moin",  Age = 21 },
	new Student() { StudentID = 3, StudentName = "Bill",  Age = 18 },
	new Student() { StudentID = 4, StudentName = "Ram", Age = 20 },
	new Student() { StudentID = 5, StudentName = "Ron", Age = 15 } 
};

// LINQ Query Syntax to find out teenager students
var teenAgerStudent = from s in studentList
                      where s.Age > 12 && s.Age < 20
                      select s;
				  
foreach(Student std in teenAgerStudent)
{			
	Console.WriteLine(std.StudentName);
}

Đây là kết quả khi biên dịch và thực thi chương trình:

John
Bill
Ron

Xem ví dụ

Trong truy vấn mẫu ở trên, phần thân biểu thức lambda s.Age > 12 && s.Age < 20 được truyền dưới dạng hàm vị ngữ Func<TSource, bool> để đánh giá mọi học sinh trong danh sách.

Ngoài ra, bạn cũng có thể sử dụng kiểu delegate Func với phương thức ẩn danh để truyền vào dưới dạng hàm vị ngữ như bên dưới (kết quả trả về đều giống nhau):

Func<Student, bool> isTeenAger = delegate(Student s) 
{ 
    return s.Age > 12 && s.Age < 20; 
};

var filteredResult = from s in studentList
                     where isTeenAger(s)
                     select s;

Bạn cũng có thể gọi bất kỳ phương thức nào khớp với tham số Func cho một trong các phương thức Where() quá tải như ví dụ dưới đây:

public static void Main()
{
    var filteredResult = from s in studentList
                         where IsTeenAger(s)
                         select s;
}

public static bool IsTeenAger(Student student)
{
    return student.Age > 12 && student.Age < 20;  
}

Phương thức Where trong cú pháp phương thức LINQ

Không giống như cú pháp truy vấn, bạn cần truyền toàn bộ biểu thức lambda dưới dạng hàm vị ngữ thay vì chỉ có phần thân biểu thức trong cú pháp phương thức LINQ. Hãy xem ví dụ sau:

// Where extension method in Method Syntax
var filteredResult = studentList.Where(s => s.Age > 12 && s.Age < 20);

Như đã đề cập ở trên, phương thức mở rộng Where cũng có phương thức quá tải thứ hai bao gồm chỉ mục của phần tử hiện tại trong danh sách. Bạn có thể sử dụng chỉ mục đó trong logic của bạn nếu bạn cần.

Ví dụ sau sử dụng phương thức mở rộng Where để lọc ra các phần tử ở vị trí lẻ trong danh sách và chỉ trả về các phần tử ở vị trí chẵn. Hãy nhớ rằng chỉ số bắt đầu từ số 0.

IList<Student> studentList = new List<Student>() 
{ 
    new Student() { StudentID = 1, StudentName = "John", Age = 18 },
    new Student() { StudentID = 2, StudentName = "Steve",  Age = 15 },
    new Student() { StudentID = 3, StudentName = "Bill",  Age = 25 },
    new Student() { StudentID = 4, StudentName = "Ram" , Age = 20 },
    new Student() { StudentID = 5, StudentName = "Ron" , Age = 19 } 
};

var filteredResult = studentList.Where((s, index) => index % 2 == 0);

foreach (var student in filteredResult)
{
    Console.WriteLine(student.StudentName);
}

Đây là kết quả khi biên dịch và thực thi chương trình:

John
Bill
Ron

Xem ví dụ

Nhiều mệnh đề where

Bạn có thể gọi mệnh đề where nhiều lần trong một truy vấn LINQ sử dụng cú pháp truy vấn.

// Multiple where clause in Query Syntax C#
var filteredResult = from s in studentList
                     where s.Age > 12
                     where s.Age < 20
                     select s;

Bạn cũng có thể gọi phương thức mở rộng Where() nhiều lần trong một truy vấn LINQ sử dụng cú pháp phương thức.

// Multiple where clause in Method Syntax C#
var filteredResult = studentList.Where(s => s.Age > 12)
                                .Where(s => s.Age < 20);

Khi sử dụng nhiều mệnh đề where thì LINQ lọc danh sách kết quả theo thứ tự của các mệnh đề where.

Như ở ví dụ trên, đầu tiên LINQ sẽ lọc ra những học sinh có tuổi lớn hơn 12 sau đó nó tiếp tục lấy những sinh viên đã được lọc ở mệnh đề where đầu tiên để lấy ra những sinh viên có tuổi nhỏ hơn 20.

Hai mệnh đề where trên tương đương với biểu thức sau: where s.Age > 12 && s.Age < 20 hoặc Where(s => s.Age > 12 && s.Age < 20).

Những điểm cần nhớ về toán tử Where:

  1. Where được sử dụng để lọc danh sách dựa trên các tiêu chí nhất định.
  2. Phương thức mở rộng Where có hai phương thức quá tải. Sử dụng phương thức quá tải thứ hai để biết chỉ mục của phần tử hiện tại trong danh sách.
  3. Cú pháp phương thức LINQ yêu cầu toàn bộ biểu thức lambda trong phương thức mở rộng Where trong khi cú pháp truy vấn chỉ yêu cầu phần thân biểu thức lambda.
  4. Có thể sử dụng nhiều mệnh đề where hoặc phương thức mở rộng Where trong một truy vấn LINQ duy nhất.