Sau khi hoàn thành bài tập này, bạn sẽ:
✅ Xây dựng lớp
SanPhamvới các thuộc tính cơ bản✅ Sử dụng static để tự động sinh mã sản phẩm
✅ Áp dụng validation cho dữ liệu
✅ Xây dựng phương thức nhập kho, xuất kho
✅ Sử dụng kiểu
decimalcho tiền tệ✅ Tính toán giá trị tồn kho tự động
BƯỚC 1: TẠO PROJECT MỚI
1.1. Mở Visual Studio
Mở Visual Studio 2022
Hoặc nhấn: Ctrl + Shift + N
1.3. Chọn loại Project
Gõ “Console” vào ô tìm kiếm
Chọn Console App (.NET Core) hoặc Console App (.NET Framework)
Nhấn Next
1.4. Đặt tên Project
Location: D:\CSharp\LapTrinhHuongDoiTuong (hoặc thư mục của bạn) Solution: LapTrinhHuongDoiTuong (chọn Add to Solution)
Nhấn Next
1.5. Chọn Framework
Chọn .NET 6.0 hoặc .NET 8.0 (LTS)
Nhấn Create
BƯỚC 2: TẠO CẤU TRÚC THƯ MỤC
2.1. Tạo thư mục Models
Trong Solution Explorer, click chuột phải vào Project
Bai2_SanPhamChọn Add → New Folder
Đặt tên:
ModelsNhấn Enter
BƯỚC 3: TẠO FILE LỚP SANPHAM
3.1. Tạo file SanPham.cs
Click chuột phải vào thư mục Models
Chọn Add → Class
Đặt tên:
SanPham.csNhấn Add
BƯỚC 4: VIẾT CODE CHO LỚP SANPHAM
4.1. Khai báo Namespace và Class
Mở file SanPham.cs và viết:
namespace Bai2_SanPham.Models { public class SanPham { // Code sẽ viết ở đây } }
4.2. Khai báo Fields (Trường dữ liệu)
{ // === FIELDS (Trường dữ liệu) === private string _maSP; // Mã sản phẩm (tự sinh) private string _tenSP; // Tên sản phẩm private decimal _donGia; // Đơn giá (dùng decimal cho tiền tệ) private int _soLuongTon; // Số lượng tồn kho private static int _soLuongSP = 0; // Đếm số SP đã tạo (static) }
Giải thích Fields:
| Field | Kiểu | Mục đích | Lưu ý |
|---|---|---|---|
_maSP | string | Lưu mã sản phẩm | Sẽ tự động sinh |
_tenSP | string | Lưu tên sản phẩm | Kiểm tra không rỗng |
_donGia | decimal | Lưu đơn giá | Dùng decimal cho tiền tệ |
_soLuongTon | int | Lưu số lượng tồn | Không được âm |
_soLuongSP | static int | Đếm số SP đã tạo | Dùng chung cho tất cả SP |
4.3. Khai báo Properties (Thuộc tính)
a. Property MaSP (Read-only – chỉ đọc)
public class SanPham { // ... Fields ở trên ... // === PROPERTIES === // 1. Mã sản phẩm - Chỉ đọc, tự sinh public string MaSP { get { return _maSP; } // Không có set → Không thể thay đổi từ bên ngoài } }
b. Property TenSP (Có validation)
// 2. Tên sản phẩm - Có kiểm tra không rỗng public string TenSP { get { return _tenSP; } set { // Kiểm tra tên không được để trống if (string.IsNullOrWhiteSpace(value)) throw new ArgumentException("Tên sản phẩm không được để trống!"); _tenSP = value.Trim(); } }
c. Property DonGia (Có validation)
// 3. Đơn giá - Không được âm public decimal DonGia { get { return _donGia; } set { if (value < 0) throw new ArgumentException("Đơn giá không được âm!"); _donGia = value; } }
d. Property SoLuongTon (Có validation)
// 4. Số lượng tồn - Không được âm public int SoLuongTon { get { return _soLuongTon; } set { if (value < 0) throw new ArgumentException("Số lượng tồn không được âm!"); _soLuongTon = value; } }
e. Property GiaTriTon (Computed – tự tính)
// 5. Giá trị tồn kho - Tự động tính (Read-only) public decimal GiaTriTon { get { return _soLuongTon * _donGia; } }
4.4. Khai báo Constructors (Phương thức khởi tạo)
a. Constructor mặc định (Tự sinh mã SP)
public class SanPham { // ... Fields và Properties ở trên ... // === CONSTRUCTORS === // Constructor 1: Không tham số - Tự sinh mã SP public SanPham() { // Tăng số lượng SP lên 1 trước _soLuongSP++; // Tự sinh mã SP: SP001, SP002, SP003, ... _maSP = "SP" + _soLuongSP.ToString("D3"); // Gán giá trị mặc định _tenSP = "Chưa xác định"; _donGia = 0; _soLuongTon = 0; } }
Giải thích:
_soLuongSP++– Tăng biến đếm lên 1ToString("D3")– Định dạng số thành 3 chữ số: 001, 002, 003, …_maSP = "SP" + "001"→ “SP001”
b. Constructor có tham số
// Constructor 2: Có tham số đầy đủ public SanPham(string tenSP, decimal donGia, int soLuongTon) : this() { // this() gọi constructor mặc định để tự sinh mã SP // Gán giá trị (có validation) TenSP = tenSP; DonGia = donGia; SoLuongTon = soLuongTon; }
Giải thích:
: this()– Gọi constructor mặc định trước (để tự sinh mã SP)Sau đó gán các giá trị khác
4.5. Khai báo Methods (Phương thức)
a. Phương thức HienThi()
public class SanPham { // ... Fields, Properties, Constructors ở trên ... // === METHODS === // 1. Hiển thị thông tin sản phẩm public void HienThi() { Console.WriteLine("═══════════════════════════════════════"); Console.WriteLine($" Mã SP : {_maSP}"); Console.WriteLine($" Tên SP : {_tenSP}"); Console.WriteLine($" Đơn giá : {_donGia:N0} VND"); Console.WriteLine($" SL Tồn : {_soLuongTon}"); Console.WriteLine($" Giá trị tồn : {GiaTriTon:N0} VND"); Console.WriteLine("═══════════════════════════════════════"); } }
b. Phương thức NhapKho()
// 2. Nhập kho (tăng số lượng tồn) public void NhapKho(int soLuong) { // Kiểm tra số lượng nhập phải > 0 if (soLuong <= 0) { Console.WriteLine("❌ Số lượng nhập phải lớn hơn 0!"); return; } // Tăng số lượng tồn _soLuongTon += soLuong; Console.WriteLine($"✓ Đã nhập kho {soLuong} sản phẩm. SL tồn: {_soLuongTon}"); }
c. Phương thức XuatKho()
// 3. Xuất kho (giảm số lượng tồn) public void XuatKho(int soLuong) { // Kiểm tra số lượng xuất phải > 0 if (soLuong <= 0) { Console.WriteLine("❌ Số lượng xuất phải lớn hơn 0!"); return; } // Kiểm tra số lượng tồn có đủ không if (soLuong > _soLuongTon) { Console.WriteLine($"❌ Không đủ hàng! Tồn: {_soLuongTon}, Yêu cầu: {soLuong}"); return; } // Giảm số lượng tồn _soLuongTon -= soLuong; Console.WriteLine($"✓ Đã xuất kho {soLuong} sản phẩm. SL tồn: {_soLuongTon}"); }
4.6. Code hoàn chỉnh của SanPham.cs
using System; namespace Bai2_SanPham.Models { public class SanPham { // === FIELDS === private string _maSP; private string _tenSP; private decimal _donGia; private int _soLuongTon; private static int _soLuongSP = 0; // === PROPERTIES === // 1. Mã sản phẩm - Read-only public string MaSP => _maSP; // 2. Tên sản phẩm - Có validation public string TenSP { get => _tenSP; set { if (string.IsNullOrWhiteSpace(value)) throw new ArgumentException("Tên sản phẩm không được để trống!"); _tenSP = value.Trim(); } } // 3. Đơn giá - Không được âm public decimal DonGia { get => _donGia; set { if (value < 0) throw new ArgumentException("Đơn giá không được âm!"); _donGia = value; } } // 4. Số lượng tồn - Không được âm public int SoLuongTon { get => _soLuongTon; set { if (value < 0) throw new ArgumentException("Số lượng tồn không được âm!"); _soLuongTon = value; } } // 5. Giá trị tồn kho - Tự động tính public decimal GiaTriTon => _soLuongTon * _donGia; // === CONSTRUCTORS === // Constructor mặc định - Tự sinh mã SP public SanPham() { _soLuongSP++; _maSP = "SP" + _soLuongSP.ToString("D3"); _tenSP = "Chưa xác định"; _donGia = 0; _soLuongTon = 0; } // Constructor có tham số public SanPham(string tenSP, decimal donGia, int soLuongTon) : this() { TenSP = tenSP; DonGia = donGia; SoLuongTon = soLuongTon; } // === METHODS === // 1. Hiển thị thông tin public void HienThi() { Console.WriteLine("═══════════════════════════════════════"); Console.WriteLine($" Mã SP : {_maSP}"); Console.WriteLine($" Tên SP : {_tenSP}"); Console.WriteLine($" Đơn giá : {_donGia:N0} VND"); Console.WriteLine($" SL Tồn : {_soLuongTon}"); Console.WriteLine($" Giá trị tồn : {GiaTriTon:N0} VND"); Console.WriteLine("═══════════════════════════════════════"); } // 2. Nhập kho public void NhapKho(int soLuong) { if (soLuong <= 0) { Console.WriteLine("❌ Số lượng nhập phải lớn hơn 0!"); return; } _soLuongTon += soLuong; Console.WriteLine($"✓ Đã nhập kho {soLuong} sản phẩm. SL tồn: {_soLuongTon}"); } // 3. Xuất kho public void XuatKho(int soLuong) { if (soLuong <= 0) { Console.WriteLine("❌ Số lượng xuất phải lớn hơn 0!"); return; } if (soLuong > _soLuongTon) { Console.WriteLine($"❌ Không đủ hàng! Tồn: {_soLuongTon}, Yêu cầu: {soLuong}"); return; } _soLuongTon -= soLuong; Console.WriteLine($"✓ Đã xuất kho {soLuong} sản phẩm. SL tồn: {_soLuongTon}"); } } }