Biểu thức khởi tạo đối tượng (Object Initialization Expressions)
Trong C# 1.x, chúng ta có thể khởi tạo các trường hoặc biến cục bộ riêng lẻ trong một khai báo duy nhất. Cú pháp dưới đây minh họa cách khởi tạo một biến đơn lẻ:
int so = 3;
string ten = "Không rõ";
KhachHang kh = new KhachHang("Tom", 32);
Khi sử dụng biểu thức khởi tạo cho kiểu tham chiếu, nó yêu cầu gọi hàm tạo của lớp, hàm này có thể chứa tham số chỉ định cách khởi tạo đối tượng. Bạn có thể sử dụng khởi tạo viên cho cả kiểu tham chiếu và kiểu giá trị.
Nếu bạn muốn khởi tạo một đối tượng (cho dù là kiểu tham chiếu hay kiểu giá trị), bạn cần có hàm tạo với đủ tham số để xác định trạng thái ban đầu của đối tượng đó. Hãy xem xét đoạn mã sau:
public class KhachHang {
public int Tuoi;
public string Ten;
public string QuocGia;
public KhachHang(string ten, int tuoi) {
this.Ten = ten;
this.Tuoi = tuoi;
}
}
Trong ví dụ trên, đối tượng KhachHang được khởi tạo bằng hàm tạo mặc định nhưng chỉ thiết lập các trường Ten và Tuoi. Nếu bạn muốn thiết lập thêm trường QuocGia, bạn có thể viết mã như sau:
KhachHang khach = new KhachHang();
khach.Ten = "Marco";
khach.QuocGia = "Italy";
C# 3.0 giới thiệu một cú pháp ngắn gọn hơn cho việc khởi tạo đối tượng, như dưới đây:
KhachHang khach = new KhachHang { Ten = "Marco", QuocGia = "Italy" };
Mặc dù cú pháp ngắn gọn hơn, nhưng sau khi biên dịch, nó hoạt động tương tự như cách truyền thống. Khởi tạo viên sẽ gọi hàm tạo phù hợp (cho cả kiểu tham chiếu và kiểu giá trị). Nếu không có dấu ngoặc trước tên loại, nó sẽ sử dụng hàm tạo mặc định. Nếu hàm tạo rỗng, thì khởi tạo viên sẽ không tốn thêm chi phí.
Các tên được chỉ định trong danh sách khởi tạo liên quan đến các trường công khai hoặc thuộc tính của đối tượng đang được khởi tạo. Cú pháp cũng cho phép gọi trực tiếp hàm tạo không mặc định, như ví dụ sau:
KhachHang kh1 = new KhachHang() { Ten = "Marco", QuocGia = "Italy" };
KhachHang kh2 = new KhachHang("Paolo", 21) { QuocGia = "Italy" };
Đoạn mã trên tương đương với:
KhachHang kh2 = new KhachHang("Paolo", 21);
kh2.QuocGia = "Italy";
Kiểu ẩn danh (Anonymous Types)
Khởi tạo viên đối tượng cũng có thể được sử dụng mà không cần khai báo lớp cụ thể. Khi làm vậy, một lớp mới - kiểu ẩn danh - sẽ được tạo ra. Xem ví dụ sau:
var kh1 = new { Ten = "Tom", Tuoi = 31 };
var kh2 = new { Ten = "Paolo", Tuoi = kh1.Tuoi };
Kiểu ẩn danh có các thuộc tính công khai và các trường riêng tư ẩn tương ứng với các tham số trong khởi tạo viên. Tên và kiểu của chúng được suy luận từ chính khởi tạo viên. Khi tên không rõ ràng, nó sẽ được suy luận từ biểu thức khởi tạo.
Tất cả các kiểu ẩn danh có cùng tên và kiểu thuộc tính sẽ được coi là cùng một lớp. Sử dụng đoạn mã sau để kiểm tra tên loại tự động sinh:
Console.WriteLine(kh1.GetType());
Console.WriteLine(kh2.GetType());
Biểu thức truy vấn (Query Expressions)
C# 3.0 giới thiệu khái niệm biểu thức truy vấn, có cú pháp tương tự SQL, dùng để thao tác dữ liệu. Dưới đây là một ví dụ về truy vấn LINQ điển hình:
var khachHangs = new[] {
new { Ten = "Marco", GiamGia = 4.5 },
new { Ten = "Paolo", GiamGia = 3.0 },
new { Ten = "Tom", GiamGia = 3.5 }
};
var truyVan =
from kh in khachHangs
where kh.GiamGia > 3
orderby kh.GiamGia
select new { Ten = kh.Ten, TyLe = kh.GiamGia / 100 };
foreach (var item in truyVan) {
Console.WriteLine(item);
}
Biểu thức truy vấn bắt đầu bằng từ khóa from và kết thúc bằng select hoặc group. Mỗi cú pháp truy vấn đều liên quan đến một phương thức chung, được giải quyết theo quy tắc áp dụng cho phương thức mở rộng.
C# 3.0 chuyển đổi biểu thức truy vấn thành dạng sau:
var truyVan = khachHangs
.Where(kh => kh.GiamGia > 3)
.OrderBy(kh => kh.GiamGia)
.Select(kh => new { Ten = kh.Ten, TyLe = kh.GiamGia / 100 });
Hãy nhớ rằng các phần tử được chọn phải tuân theo thứ tự và kiểu dữ liệu đã định nghĩa.