So sánh
Equals và '=='
Đặc điểm | Toán tử | Phương thức |
|---|---|---|
Loại so sánh mặc định | Kiểu tham chiếu (class): mặc định so sánh tham chiếu (trừ khi kiểu đó overload
| Kiểu tham chiếu (class): mặc định là tham chiếu như |
Ghi đè / tuỳ biến | Có thể overload (không phải override) bằng cách khai báo | Có thể override (virtual method Với generics/hiệu năng, nên triển khai |
Tính linh hoạt | Ít linh hoạt hơn (chỉ 1 toán tử; phải cẩn thận tương thích với | Linh hoạt hơn: có thể override/triển khai |
Tốc độ | Không có quy tắc “nhanh hơn” nói chung. Với | Tương tự: phụ thuộc kiểu cụ thể và triển khai |
Sử dụng với
| An toàn (không ném NRE); | Gọi instance |
Generic và Non-Generic
Đặc điểm | Non-generic | Generic |
|---|---|---|
Khái niệm | Là kiểu dữ liệu truyền thống. Không khai báo cụ thể khi định nghĩa class, method, interface. Kiểu dữ liệu thực tế được xác định khi sử dụng. | Là kiểu dữ liệu được tham số hoá bởi một hoặc nhiều kiểu khác nhau. Cho phép khai báo class, method, interface với kiểu cụ thể. Kiểu này sẽ được định nghĩa và sử dụng xuyên suốt. |
Ưu điểm | Đơn giản, dễ hiểu Hiệu quả cao hơn với các kiểu dữ liệu nguyên thuỷ | Tăng khả năng tái sử dụng code Đảm bảo an toàn dữ liệu vào và ra khi sử dụng Tốt hơn do được tối ưu hoá cho kiểu dữ liệu cụ thể |
Nhược điểm | Kém linh hoạt, khó tái sử dụng. Thiếu an toàn do có thể sử dụng sai kiểu dữ liệu | Phức tạp hơn so với non-generic. Có thể ảnh hưởng hiệu suất với những kiểu dữ liệu phức tạp. |
Sử dụng | Khi cần code đơn giản dễ hiểu, không yêu cầu tái sử dụng cao, không yêu cầu an toàn dữ liệu cao. | Khi cần code có khả năng tái sử dụng cao và yêu cầu tính an toàn dữ liệu cao. |
Delegate và Event
Delegate | Event |
|---|---|
- Là một tham chiếu đại diện cho phương thức. - Có thể gọi trực tiếp từ bất kỳ đâu có quyền truy cập. - Có thể gọi trực tiếp mà không có cơ chế bảo vệ nào nên có thể dẫn đến lỗi. - Ưu tiên tính linh hoạt. | - Là thành phần của lớp sử dụng delegate để quản lý danh sách các phương thức. - Chỉ có thể kích hoạt bên trong lớp mà nó được khai báo. - Có cơ chế bảo vệ ngăn chặn gọi từ bên ngoài. Chỉ cho phép đăng ký bên trong class thông quan += hoặc huỷ đăng ký qua -= - Ưu tiên an toàn và kiểm soát. |
Struct và Class
Tiêu chí | struct | class |
|---|---|---|
Bản chất | Kiểu giá trị (value type) | Kiểu tham chiếu (reference type) |
Cấp phát & bộ nhớ | Nằm trên stack hoặc heap tùy vào nơi nó sống. Sao chép theo giá trị | Luôn cấp phát trên heap, biến giữ tham chiếu Sao chép tham chiếu |
Vòng đời & GC | Không tạo đối tượng riêng trên heap ⇒ ít áp lực GC (trừ khi bị boxing) | Đối tượng do GC quản lý; cần cân nhắc phân bổ/thu hồi. |
Kế thừa | Không kế thừa class; chỉ implement interface | Có inheritance + implement interface |
Constructor mặc định | Luôn có tự định nghĩa constructor không tham số | Tự do định nghĩa constructor; không có zero-init bắt buộc |
Nullability | Không thể | Có thể |
Equality mặc định | So sánh theo giá trị (field-by-field) | So sánh tham chiếu (trừ khi override/record) |
Boxing | Bị boxing khi chuyển sang | Không có khái niệm boxing |
Bất biến/biến đổi | Nên thiết kế nhỏ & bất biến (immutable) để tránh chi phí copy | Linh hoạt cho đối tượng phức tạp, nhiều trạng thái |
Hiệu năng (quy tắc thực tế) | Tốt cho dữ liệu nhỏ (≈ ≤ 16–32 byte), sống ngắn, dùng thường xuyên; tránh struct lớn/mutable vì tốn copy | Tốt cho mô hình phức tạp, cần chia sẻ qua tham chiếu, vòng đời dài |
Generics | Tránh boxing với | Ràng buộc |
Khi nên dùng | Để lưu những dữ liệu đơn giản, bất biến. | Đa phần các đối tượng có đối tượng có dữ liệu, hành vi phức tạp.. |
Unity lưu ý | Dùng struct (hoặc Cẩn thận copy trong Update | Dùng class cho |
Abstract class và Interface
Tiêu chí | Abstract class | Interface |
|---|---|---|
Định nghĩa | Là lớp nền tảng có biến chung và một phần code sẵn. Lớp con kế thừa và hoàn thiện. | Là bản hợp đồng liệt kê chức năng. Lớp/struct thực hiện (implement) các chức năng đó. |
Access Modifiers | Có | Không. Mặc định là public |
Field, Method dùng chung | Có | Có thể có method mặc định (từ C# 8 trở lên), nhưng không có field, constructor |
Kế thừa / triển khai | Mỗi lớp chỉ kế thừa 1 abstract class. | Một lớp/struct có thể implement nhiều interface. |
Dùng cho struct | Không dùng cho struct. | Dùng được cho struct. |
Khi nên dùng | Dùng để tạo một bản thiết kế chung cho các đối tượng liên quan đến nhau. Cung cấp các chi tiết mà các đối tượng đó phải tuân theo. Khi cần constructor. | Tạo ra một vai trò/chức năng mà các đối tượng triển khai nó sẽ đảm nhiệm. |
Ưu điểm | Tái sử dụng code mạnh, quản lý chung dễ, thêm thành viên thường ít phá vỡ lớp con. | Linh hoạt, áp dụng rộng (kể cả struct), hỗ trợ nhiều vai trò, rất hợp cho test/DI. |
Nhược điểm | Ràng buộc thừa kế (chỉ 1 lớp cha), dễ tạo cây thừa kế sâu nếu lạm dụng. | Không có dữ liệu chung; nếu thêm phương thức mới có thể ảnh hưởng kiểu đã implement (giảm rủi ro nhờ “method mặc định” từ C# 8). |
Ví dụ Unity |
|
|
Stack và Heap
Tiêu chí | Stack | Heap |
|---|---|---|
Bản chất | Vùng nhớ tạm cho biến cục bộ & method | Vùng nhớ động cho đối tượng sống lâu |
Lưu gì | Giá trị của biến cục bộ (bao gồm struct nhỏ), con trỏ return address | Object của class, mảng, struct nằm trong object/mảng, dữ liệu boxed |
Cấp phát/giải phóng | Rất nhanh theo kiểu LIFO, trong method | Linh hoạt: cấp phát tự do, thu gom bởi GC |
Quản lý | Tự động khi vào/ra hàm (không có GC) | Managed heap do GC quản lý (Gen0/1/2, LOH) |
Tốc độ | Rất nhanh, liên tục, cache-friendly | Chậm hơn stack; có thể bị tạm dừng (GC pause) |
Kích thước | Giới hạn (stack size) | Rộng hơn, tùy RAM/GC |
Thời gian sống | Ngắn, theo phạm vi hàm | Dài/linh hoạt, theo tham chiếu còn sống |
Khi nào xảy ra | Biến cục bộ, tham số, struct cục bộ |
|
Lưu ý quan trọng | Dữ liệu biến mất khi ra khỏi hàm | Tránh rác nhiều/đối tượng lớn gây áp lực GC/LOH |
For và Foreach
Tiêu chí | for | foreach |
|---|---|---|
Khái niệm | Vòng lặp theo index ( | Vòng lặp duyệt từng phần tử qua enumerator. |
Cách hoạt động | Truy cập | Gọi |
Truy cập theo index | Có | Không có |
Sửa phần tử | Có thể Sửa phần tử chỉ định qua index | Không thể sửa trong vòng lặp |
Thêm/Xóa khi lặp | Có thể làm được (cẩn thận cập nhật chỉ số; thường lặp ngược khi xóa) | Không được thay đổi collection đang duyệt → dễ ném |
Hiệu năng (thực tế) | Rất nhanh cho mảng và khi cần truy cập ngẫu nhiên | Rất nhanh cho List (enumerator là struct, thường không cấp phát); nhìn chung chênh lệch nhỏ, chọn theo độ rõ ràng |
Độ rõ ràng mã | Tốt khi cần index/điều kiện bước nhảy tùy biến | Ngắn gọn, dễ đọc khi chỉ duyệt |
Khi nên dùng | Cần index, cần chèn/xóa trong lúc lặp, hoặc cần nhảy bước | Duyệt đọc, không chỉnh sửa cấu trúc collection, code gọn |
Lỗi thường gặp | Quên cập nhật | Thêm/xóa trong vòng lặp. |
Static và non-Static
Class
Tiêu chí | Static | Non-static |
|---|---|---|
Khởi tạo | Không thể | Có thể |
Thành viên | Tất cả phải là static | Có cả instance và static |
Kế thừa | Không kế thừa/không implement interface; ngầm | Có thể kế thừa/implement interface |
Dùng khi | Nhóm hàm tiện ích/hằng số không cần state riêng | Mô hình đối tượng có state/đa hình |
field/method/property
Tiêu chí | Static | Non-static |
|---|---|---|
Thuộc về | Class | Instance |
Truy cập |
|
|
Vòng đời | Tồn tại suốt thời gian chạy | Sống theo vòng đời instance (GC) |
Trạng thái | Chung toàn cục → cần chú ý thread-safety | Tách biệt theo từng đối tượng |
Dùng khi | Cấu hình bất biến, cache dùng chung, hằng số | Dữ liệu/hành vi gắn với một đối tượng |