1. Giá trị mặc định cho tham số
Hãy tưởng tượng bạn đi uống cà phê: nếu không nói rõ có cần đường không, barista sẽ tự động cho một muỗng. Nhưng đôi khi bạn lại muốn... hai muỗng! Hoặc không đường luôn (quá chất!). Method cũng vậy: đôi lúc tiện nhất là một số tham số sẽ nhận giá trị mặc định nếu bạn không truyền vào.
Còn tham số đặt tên thì giống như khi order cà phê mà bảo: "Cho mình sữa đậu nành nhé, không phải sữa thường", bất kể thứ tự nguyên liệu ra sao.
Trong C# cả hai cơ chế này giúp code của bạn gọn gàng, dễ hiểu và giảm lỗi. Chúng xuất hiện rất nhiều trong project thực tế: từ thư viện .NET đến các framework nổi tiếng — nên nhà tuyển dụng rất thích thấy bạn dùng thành thạo mấy cái này.
Cú pháp
Giá trị mặc định cho tham số được đặt ngay trong khai báo method bằng dấu =. Nếu khi gọi method mà không truyền tham số đó, giá trị mặc định sẽ được dùng.
void PrintStudent(string name, int age = 18)
{
Console.WriteLine($"Sinh viên: {name}, tuổi: {age}");
}
Nó hoạt động thế nào?
- Nếu gọi PrintStudent("Алиса"); — sẽ in ra: Sinh viên: Алиса, tuổi: 18.
- Nếu gọi PrintStudent("Саша", 22); — sẽ in ra: Sinh viên: Саша, tuổi: 22.
Có dùng được cho mọi kiểu không?
Bạn có thể đặt giá trị mặc định cho bất kỳ kiểu tham số nào, nhưng có vài điểm cần chú ý:
- Với kiểu tham chiếu (string, class, v.v.): mặc định có thể là null hoặc literal cụ thể.
- Với kiểu giá trị (int, double, bool, v.v.): dùng literal đúng kiểu đó.
- Với enum, struct: cũng có thể dùng giá trị mặc định luôn.
void AddStudent(string name, int course = 1, double averageScore = 5.0, string comment = null)
{
Console.WriteLine($"Đã thêm sinh viên: {name}, khóa: {course}, điểm trung bình: {averageScore}, nhận xét: {comment}");
}
Gọi thử:
- AddStudent("Иван");
- AddStudent("Мария", 2);
- AddStudent("Фёдор", 2, 4.7, "Xuất sắc");
Thứ tự tham số có giá trị mặc định
Tất cả tham số không bắt buộc (có giá trị mặc định) phải nằm bên phải (sau các tham số bắt buộc). Nếu bạn cố đặt tham số mặc định trước tham số bắt buộc, compiler sẽ "giận dỗi" ngay.
// Lỗi!
void Test(int a = 1, int b)
{
// ...
}
Tại sao lại vậy? Vì nếu không, compiler sẽ không biết tham số nào ứng với đối số nào khi gọi method.
2. Tham số đặt tên
Mặc định, khi gọi method và truyền đối số, thứ tự phải đúng như khai báo trong method. Nhưng đôi khi danh sách dài, có tham số mặc định, dễ nhầm lắm.
Tham số đặt tên cho phép bạn chỉ rõ đối số nào ứng với tham số nào, theo bất kỳ thứ tự nào.
AddStudent(name: "Елизавета", averageScore: 4.2, comment: "Sinh viên xuất sắc nhất kỳ");
- Ở đây không truyền khóa học (course), nên nó sẽ là 1 (mặc định).
- Không cần nhớ tham số comment ở vị trí thứ mấy — cứ ghi tên nó ra là được.
Bạn thậm chí có thể đảo thứ tự tham số:
AddStudent(averageScore: 3.7, name: "Георгий");
Rất tiện lợi, code nhìn cũng dễ hiểu hơn hẳn!
Kết hợp với tham số vị trí
Bạn có thể trộn tham số đặt tên và tham số vị trí (không tên), nhưng tất cả tham số vị trí phải nằm trước tham số đặt tên.
// Đúng
AddStudent("Сергей", averageScore: 4.9);
// Lỗi
AddStudent(course: 2, "Филипп");
Sau tham số đặt tên đầu tiên, các tham số còn lại phải là đặt tên. Compiler kiểm tra rất kỹ thứ tự này để tránh lỗi bất ngờ.
Tiện lợi khi method có nhiều tham số
Cách này rất hay khi dùng method có nhiều option phụ. Ví dụ, nếu bạn viết function để thêm user vào database cloud nào đó:
void RegisterUser(
string username,
string password,
string email = null,
bool admin = false,
bool sendWelcomeEmail = true,
string language = "ru"
)
Gọi mà không dùng tham số đặt tên thì nhìn hơi "khoai":
RegisterUser("cat", "qwerty", null, false, true, "ru");
Dùng tham số đặt tên thì rõ ràng, dễ hiểu:
RegisterUser("cat", "qwerty", admin: true, sendWelcomeEmail: false, language: "en");
Mẹo nhỏ: dùng tham số đặt tên để code dễ đọc, khỏi cần tài liệu luôn!
3. Lưu ý khi dùng và lỗi thường gặp
Mới bắt đầu dùng giá trị mặc định và tham số đặt tên thì dễ dính lỗi lắm.
- Thứ tự tham số. Luôn để tham số mặc định sau tham số bắt buộc. Đảo ngược là compiler báo lỗi ngay.
- Thay đổi giá trị mặc định trong thư viện. Nếu bạn đổi giá trị mặc định trong thư viện, client cũ sẽ không tự động dùng giá trị mới đâu. Giá trị mặc định được compile vào code gọi method. Nên hãy cân nhắc kỹ trước khi đổi giá trị mặc định trong thư viện public.
- Trộn tham số vị trí và đặt tên. Nếu bạn trộn hai loại này mà sau tham số đặt tên lại truyền tham số vị trí — sẽ lỗi ngay. Ví dụ: Func(a: 1, 2) — lỗi liền.
- Sai tên tham số. Compiler rất nghiêm: nếu bạn gõ nhầm (ví dụ naem: "Миша"), sẽ báo lỗi kiểu: "Không có tham số này, bạn đang làm gì vậy?!".
GO TO FULL VERSION