Classes, structs, và records là những khái niệm cơ bản trong lập trình C#. Mỗi loại đều có đặc điểm, tính năng và giới hạn riêng, phù hợp với từng trường hợp sử dụng khác nhau. Trong bài viết này, chúng ta sẽ cùng tìm hiểu cách lựa chọn giữa chúng dựa trên hiệu suất, tính linh hoạt và khả năng tối ưu hóa.
Class trong C#
Class là kiểu tham chiếu (reference type). Điều này có nghĩa là một biến kiểu class lưu trữ tham chiếu đến đối tượng, không phải dữ liệu thực. Vì thế, bạn có thể có nhiều tham chiếu cùng trỏ đến một đối tượng duy nhất. Khi một tham chiếu thay đổi, các tham chiếu khác cũng bị ảnh hưởng.
Class hỗ trợ các khái niệm cơ bản của lập trình hướng đối tượng (OOP) như: trừu tượng hóa, đóng gói, kế thừa, và đa hình. Điều này làm cho class trở thành lựa chọn hàng đầu khi bạn cần xây dựng các logic phức tạp và sử dụng tính năng của OOP.
Cú pháp định nghĩa class:
<modifiers> class <tên_lớp>
{
// Các thành viên dữ liệu và hàm thành viên
}
Ví dụ minh họa:
public class TacGia
{
public int MaTacGia { get; set; }
public string Ho { get; set; }
public string Ten { get; set; }
public string DiaChi { get; set; }
public string Email { get; set; }
public string SoDienThoai { get; set; }
}
Tạo đối tượng từ class:
var tacGia = new TacGia
{
MaTacGia = 1,
Ho = "Nguyễn",
Ten = "Trãi",
DiaChi = "Hà Nội, Việt Nam",
Email = "nguyentrai@example.com",
SoDienThoai = "0123456789"
};
Struct trong C#
Struct là kiểu giá trị (value type). Biến kiểu struct lưu trữ giá trị thực thay vì tham chiếu. Vì thế, khi bạn truyền một struct làm tham số cho phương thức hoặc gán nó cho một biến khác, giá trị của nó sẽ được sao chép.
Struct thích hợp để tạo các kiểu dữ liệu nhỏ gọn, tránh chi phí của garbage collection. Struct cũng có thể bất biến nếu sử dụng từ khóa readonly
.
Cú pháp định nghĩa struct:
<modifiers> struct <tên_struct>
{
// Các thành viên dữ liệu và hàm thành viên
}
Ví dụ minh họa:
struct ToaDo
{
public int X;
public int Y;
}
Tạo đối tượng từ struct:
ToaDo diem = new ToaDo();
diem.X = 10;
diem.Y = 20;
Record trong C#
Record được giới thiệu trong C# 9, là kiểu tham chiếu với đặc điểm bất biến mặc định (immutable). Record hỗ trợ so sánh giá trị theo bản chất thay vì so sánh tham chiếu, tương tự struct, nhưng vẫn là kiểu tham chiếu.
Record thích hợp để đại diện cho các kiểu dữ liệu truyền tải (DTO), cấu trúc dữ liệu bất biến và các đối tượng yêu cầu tính an toàn luồng (thread-safe).
Ví dụ minh họa:
public record HinhChuNhat(int ChieuDai, int ChieuRong);
Tạo đối tượng từ record:
var hinh = new HinhChuNhat(10, 5);
Kế thừa trong record
Record có thể kế thừa từ record khác nhưng không thể kế thừa từ class.
public record Nguoi(string Ho, string Ten, string DiaChi);
public record TacGia(int MaTacGia, string SachGanDay, string Ho, string Ten, string DiaChi)
: Nguoi(Ho, Ten, DiaChi);
Tạo đối tượng từ record kế thừa:
var tacGia = new TacGia(1, "Bình Ngô Đại Cáo", "Nguyễn", "Trãi", "Hà Nội, Việt Nam");
So sánh class, struct và record
Đặc điểm | Class | Struct | Record |
---|---|---|---|
Loại | Tham chiếu (reference) | Giá trị (value) | Tham chiếu (reference) |
Bất biến | Không | Có thể | Có mặc định |
Hiệu suất | Chậm hơn (GC overhead) | Hiệu suất cao hơn | Trung bình |
Kế thừa | Có | Không | Có, chỉ giữa các record |
So sánh bằng | Tham chiếu | Giá trị | Giá trị |
Khi nào nên sử dụng?
- Class: Khi bạn cần logic phức tạp hoặc các tính năng OOP như kế thừa, đa hình.
- Struct: Khi cần hiệu suất cao và chỉ lưu trữ dữ liệu nhỏ, ít phức tạp (dưới 16 byte).
- Record: Khi cần làm việc với dữ liệu bất biến, hỗ trợ lập trình hàm, hoặc so sánh giá trị.
Bằng cách hiểu rõ mục đích sử dụng và đặc điểm của từng loại, bạn có thể xây dựng các ứng dụng C# mạnh mẽ, hiệu quả và tối ưu hóa tốt hơn.