Làm việc với các loại ẩn danh trong LINQ
Kiểu ẩn danh rất tiện lợi, vì tên kiểu được xác định tự động tại thời điểm biên dịch. Tuy nhiên, chúng có những hạn chế của chúng. Hướng dẫn này cung cấp cho bạn cái nhìn tổng quan và các ví dụ thực tế về cách làm việc với các kiểu ẩn danh trong LINQ.
Để bắt đầu hướng dẫn này, chúng ta hãy xem nhanh một ví dụ cơ bản cho thấy cách khai báo kiểu ẩn danh:
- var myAnonymousType = new { Name = "Patty", Age = 25, IsMale = false };
Một số quy tắc để khai báo một kiểu ẩn danh:
Lý do nó không thể được gán null, là vì không có kiểu nào bị ràng buộc không có null.
Điều tuyệt vời về các kiểu ẩn danh được sử dụng với LINQ là bạn không phải suy nghĩ về việc truyền kiểu kết quả cho các truy vấn của mình. Điều này đặc biệt hữu ích khi bạn làm việc với các kiểu có nhiều thuộc tính. Trình biên dịch sẽ thay thế từ khóa var bằng một kiểu thực, luôn là kiểu tham chiếu.
Hãy xem điều này trong hành động:
- var people = new[] {
- new { Name = "Patty", Age = 25, IsMale = false },
- new { Name = "Kenny", Age = 43, IsMale = true },
- new { Name = "Kate", Age = 37, IsMale = false }
- };
- var res = people.Where(p => p.Name.StartsWith("K")).Select(p => p);
- foreach (var person in res)
- Console.WriteLine(person.Name);
- // Outputs:
- // Kenny
- // Kate
Ví dụ này đưa tất cả mọi người từ kiểu mảng bắt đầu bằng chữ “K” trong tên của họ và in họ ra màn hình. Vì vậy, cả people và res đều là loại ẩn danh.
Các loại ẩn danh là bất biến, có nghĩa là chúng không thể thay đổi sau khi được tạo (về cơ bản có nghĩa là chúng ở chế độ chỉ đọc). Vì vậy, bạn không thể làm điều này:
- var people = new[] {
- new { Name = "Patty", Age = 25, IsMale = false },
- new { Name = "Kenny", Age = 43, IsMale = true },
- new { Name = "Kate", Age = 37, IsMale = false }
- };
- var res = people.Where(p => p.Name.StartsWith("K")).Select(p => p);
- res.First().Age = 27; // <- this won’t compile, as res is immutable!
Tuy nhiên, sẽ hoàn toàn ổn nếu sử dụng res để mở rộng truy vấn hiện có, vì sau đó chúng tôi đang làm việc trên các kiểu ẩn danh giống nhau, mà trình biên dịch đã nhận ra:
However, it will be perfectly fine to use res to expand the existing query, because we are then working on the same anonymous types, which the compiler already will recognize:
- var people = new[] {
- new { Name = "Patty", Age = 25, IsMale = false },
- new { Name = "Kenny", Age = 43, IsMale = true },
- new { Name = "Kate", Age = 37, IsMale = false }
- }
- var res = people.Where(p => p.Name.StartsWith("K")).Select(p => p);
- res = people.Where(p => p.Age >= 40).Select(p => p); // < ok
- foreach (var person in res)
- console.writeline(person.name);
Giới hạn này của các kiểu ẩn danh là không thể thay đổi thường sẽ không phải là vấn đề, nhưng nếu bạn cần thay đổi các giá trị bên trong của một kiểu ẩn danh, bạn có thể chuyển dữ liệu cho một lớp được đặt tên và sau đó thay đổi dữ liệu.
Vì một kiểu ẩn danh được lấy trực tiếp từ System.Object, nó luôn triển khai các phương thức Equals (), GetHashCode () và ToString (). Điều đáng nói là Equals () và GetHashcode () coi hai trường hợp của kiểu ẩn danh là ngang nhau, khi tất cả các thuộc tính của chúng đều bằng nhau.
Một kiểu ẩn danh không thể dễ dàng được trả về từ một phương thức vì nó có cái được gọi là phạm vi phương thức. Một cách để giải quyết vấn đề này là chuyển đổi kiểu ẩn danh thành một đối tượng trước khi nó được trả lại.
Như bạn đã thấy trong hướng dẫn ngắn này, các kiểu ẩn danh có thể làm cho cuộc sống của nhà phát triển .NET sử dụng LINQ trở nên thuận tiện hơn rất nhiều. Tôi hy vọng bây giờ bạn có một cái nhìn tốt hơn về những ưu điểm và hạn chế của nó.
Đăng nhận xét