Toán tử định lượng trong LINQ

Các toán tử định lượng đánh giá các phần tử của danh sách dựa trên một số điều kiện và trả về giá trị boolean để chỉ ra rằng một số hoặc tất cả các phần tử thỏa mãn điều kiện.

Bảng sau liệt kê tất cả toán tử định lượng có sẵn trong LINQ:

Toán tử Mô tả
All Kiểm tra nếu tất cả các phần tử trong danh sách thỏa mãn điều kiện đã chỉ định thì trả về true, ngược lại trả về false.
Any Kiểm tra nếu bất kỳ phần tử nào trong danh sách thỏa mãn điều kiện đã chỉ định thì trả về true, ngược lại trả về false.
Contains Kiểm tra nếu danh sách chứa một phần tử được chỉ định thì trả về true, ngược lại trả về false.

Toán tử định lượng là một trong những toán tử truy vấn chuẩn của LINQ.

Toán tử truy vấn chuẩn của LINQ | Comdy
Các toán tử truy vấn chuẩn trong LINQ là các phương thức mở rộng cho các kiểu IEnumerable<T> và IQueryable<T>.

Toán tử All trong LINQ

Toán tử All đánh giá từng phần tử trong tập hợp đã cho theo một điều kiện được chỉ định và trả về true nếu tất cả các phần tử thỏa mãn một điều kiện, ngược lại sẽ trả về false.

Ví dụ dưới đây minh họa sử dụng phương thức mở rộng All trong LINQ:

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 } 
};

// checks whether all the students are teenagers    
bool areAllStudentsTeenAger = studentList.All(s => s.Age > 12 && s.Age < 20);

Console.WriteLine(areAllStudentsTeenAger);

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

false
Lưu ý: Toán tử All không hỗ trợ cú pháp truy vấn LINQ.

Toán tử Any trong LINQ

Toán tử Any kiểm tra xem bất kỳ phần tử nào trong danh sách đáp ứng điều kiện đã chỉ định hay không? Nếu có sẽ trả về true, ngược lại sẽ trả về false.

Trong ví dụ sau, phương thức mở rộng Any được sử dụng để kiểm tra xem có học sinh nào là thiếu niên hay không.

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 } 
};
 
bool isAnyStudentTeenAger = studentList.Any(s => s.age > 12 && s.age < 20);

Console.WriteLine(isAnyStudentTeenAger);

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

true
Lưu ý: Toán tử Any không hỗ trợ cú pháp truy vấn LINQ.

Toán tử Contains trong LINQ

Toán tử Contains kiểm tra xem một phần tử đã chỉ định có tồn tại trong danh sách hay không và trả về kiểu boolean. Nếu phần tử tồn tại trong danh sách thì sẽ trả về true, ngược lại sẽ trả về false.

Phương thức mở rộng Contains có hai phương thức quá tải. Phương thức quá tải đầu tiên yêu cầu một giá trị để kiểm tra trong danh sách và phương thức quá tải thứ hai yêu cầu tham số bổ sung kiểu IEqualityComparer để tạo các điều kiện so sánh bằng nhau tùy chỉnh.


public static bool Contains<TSource>(this IEnumerable<TSource> source, 
    TSource value);

public static bool Contains<TSource>(this IEnumerable<TSource> source, 
    TSource value, 
    IEqualityComparer<TSource> comparer);

Như đã đề cập ở trên, phương thức mở rộng Contains yêu cầu một giá trị để kiểm tra làm tham số đầu vào. Kiểu của giá trị này phải giống với kiểu dữ liệu của danh sách generic.

Ví dụ sau minh họa phương thức Contains kiểm tra xem giá trị 5 có tồn tại trong danh sách hay không. Xin lưu ý rằng kiểu dữ liệu của danh sách là kiểu int.

IList<int> intList = new List<int>() { 1, 2, 3, 4, 5 };

bool result = intList.Contains(5);

Console.WriteLine(result);

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

true

Ví dụ trên hoạt động tốt với các kiểu dữ liệu nguyên thủy. Tuy nhiên, nó sẽ không hoạt động với một lớp tùy chỉnh. Hãy xem xét ví dụ sau:

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 } 
};
 
Student std = new Student(){ StudentID = 3, StudentName = "Bill", Age = 18 };

bool result = studentList.Contains(std);

Console.WriteLine(result);

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

false

Như bạn có thể thấy trong ví dụ trên, phương thức Contains trả về false ngay cả khi sinh viên "Bill" tồn tại trong danh sách studentList.

Điều này là do phương thức mở rộng Contains chỉ so sánh tham chiếu của một đối tượng chứ không phải các giá trị thực tế của một đối tượng.

Do trong ví dụ trên std là đối tượng khác với các đối tượng sinh viên trong danh sách nên sẽ có tham chiếu khác nhau và phương thức Contains trả về false.

Vì vậy, để so sánh các giá trị của đối tượng sinh viên, bạn cần tạo một lớp bằng cách triển khai interface IEqualityComparer, so sánh các giá trị của hai đối tượng Student và trả về boolean.

Sau đây là lớp StudentComparer triển khai interface IEqualityComparer<Student> để so sánh các giá trị của hai đối tượng Student:

class StudentComparer : IEqualityComparer<Student>
{
    public bool Equals(Student x, Student y)
    {
        return x.StudentID == y.StudentID && 
            x.StudentName.ToLower() == y.StudentName.ToLower();			
    }

    public int GetHashCode(Student obj)
    {
        return obj.GetHashCode();
    }
}

Bây giờ, bạn có thể sử dụng lớp StudentComparer ở trên trong phương thức quá tải thứ hai của phương thức mở rộng Contains. Phương thức này chấp nhận tham số thứ hai có kiểu IEqualityComparer, như sau:

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 } 
};
 
Student std = new Student() { StudentID = 3, StudentName = "Bill", Age = 18 };

bool result = studentList.Contains(std, new StudentComparer());

Console.WriteLine(result);

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

true

Vì vậy, bạn phải sử dụng lớp so sánh để có được kết quả chính xác từ phương thức mở rộng Contains cho các lớp tùy chỉnh.

Lưu ý: Toán tử Contains không hỗ trợ cú pháp truy vấn LINQ.

Những điểm cần nhớ về toán tử định lượng trong LINQ

  1. All, Any và Contains là các toán tử định lượng trong LINQ.
  2. All kiểm tra nếu tất cả các phần tử trong một danh sách thỏa mãn điều kiện đã chỉ định. Nếu thỏa mãn sẽ trả về true, ngược lại trả về false.
  3. Any kiểm tra nếu bất kỳ phần tử nào trong danh sách thỏa mãn điều kiện đã chỉ định. Nếu thỏa mãn sẽ trả về true, ngược lại trả về false.
  4. Contains kiểm tra xem phần tử được chỉ định có tồn tại trong danh sách hay không. Nếu thỏa mãn sẽ trả về true, ngược lại trả về false.
  5. Sử dụng lớp tùy chỉnh triển khai từ interface IEqualityOperator với phương thức Contains để kiểm tra đối tượng trong danh sách kiểu phức tạp.
  6. All, Any và Contains không hỗ trợ cú pháp truy vấn LINQ.
LINQ
Bài Viết Liên Quan:
Truy vấn LINQ phức tạp
Trung Nguyen 23/04/2020
Truy vấn LINQ phức tạp

Bạn sẽ tìm hiểu một số truy vấn LINQ phức tạp trong hướng dẫn này.

Từ khóa let, into trong LINQ
Trung Nguyen 23/04/2020
Từ khóa let, into trong LINQ

Từ khóa let, into trong LINQ có tác dụng gì? Hướng dẫn khai báo và sử dụng từ khóa let, into trong LINQ.

Thực thi truy vấn LINQ
Trung Nguyen 23/04/2020
Thực thi truy vấn LINQ

Trì hoãn thực thi truy vấn LINQ là gì? Thực thi ngay lập tức truy vấn LINQ là gì? Làm sao để thực thi truy vấn LINQ.

Expression trong LINQ
Trung Nguyen 23/04/2020
Expression trong LINQ

Expression trong LINQ là gì? Cây biểu thức trong LINQ là gì? Cách khai báo và sử dụng chúng trong LINQ.