Ngôn ngữ LINQ - Toán tử Contains
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.
Những điểm cần nhớ về toán tử định lượng trong LINQ
- All, Any và Contains là các toán tử định lượng trong LINQ.
- 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.
- 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.
- 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.
- 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.
- All, Any và Contains không hỗ trợ cú pháp truy vấn LINQ.