Khái niệm
Named Parameters cho phép chỉ định tham số theo tên thay vì vị trí khi gọi method. Giúp code dễ đọc, không cần nhớ thứ tự tham số.
Cú pháp
// Thay vì: Method(10, 20, 30);
// Có thể:
Method(first: 10, second: 20, third: 30);
Method(third: 30, first: 10, second: 20); // Thứ tự tùy ý
Ví dụ cơ bản
using System;
class Demo
{
static void Main()
{
// Gọi thông thường (positional)
PrintName("James", "Bond");
// Named parameters - thứ tự tự do
PrintName(firstName: "Mark", lastName: "Wood");
PrintName(lastName: "Federer", firstName: "Roger");
// Mix: positional trước, named sau (bắt buộc)
PrintName("John", lastName: "Doe");
// PrintName(firstName: "John", "Doe"); // ❌ Lỗi compile: named argument phải sau positional
}
static void PrintName(string firstName, string lastName)
{
Console.WriteLine($"FullName: {firstName} {lastName}");
}
}
Kết quả
FullName: James Bond FullName: Mark Wood FullName: Roger Federer FullName: John Doe
Quy tắc quan trọng
- Named arguments phải đứng sau positional arguments.
- Tên tham số phải khớp chính xác với định nghĩa method (case-sensitive).
- Có thể mix:
Method(1, 2, third: 3, fourth: 4). - Không thể bỏ qua tham số bắt buộc (required parameters) - trừ khi có default value.
Kết hợp với Optional Parameters
void Config(string server, int port = 80, bool ssl = false, int timeout = 30) { ... }
// Gọi linh hoạt
Config("localhost"); // Tất cả default
Config("localhost", 443); // port=443, ssl=false, timeout=30
Config("localhost", ssl: true); // port=80, ssl=true, timeout=30
Config("localhost", timeout: 60, ssl: true); // port=80, ssl=true, timeout=60
Config(server: "prod", port: 443, ssl: true); // Rõ ràng, dễ đọc
Use Cases thực tế
1. Method với nhiều tham số cùng kiểu
// Dễ nhầm lẫn thứ tự
void DrawRect(int x, int y, int width, int height, int borderWidth, Color borderColor, Color fillColor) { }
// Named parameters: Rõ ràng ngay lập tức
DrawRect(x: 10, y: 20, width: 100, height: 50, borderWidth: 2, borderColor: Color.Red, fillColor: Color.Blue);
2. API Fluent / Builder Pattern
var request = new HttpRequestBuilder()
.WithUrl("https://api.example.com")
.WithMethod(HttpMethod.Post)
.WithHeader("Authorization", "Bearer token")
.WithTimeout(TimeSpan.FromSeconds(30))
.Build();
3. Unit Test - Data driven
[Theory]
[InlineData(expected: 4, a: 2, b: 2)]
[InlineData(expected: 10, a: 3, b: 7)]
public void Add_ReturnsSum(int expected, int a, int b)
{
Assert.Equal(expected, Calculator.Add(a, b));
}
Named Arguments trong Delegate/Lambda
Func<int, int, int, string> format = (x, y, z) => $"{x}-{y}-{z}";
// Không hỗ trợ named arguments trực tiếp trên delegate invoke
// format(x: 1, y: 2, z: 3); // ❌ Lỗi
// Nhưng có thể dùng local function hoặc expression
var formatNamed = new Func<int, int, int, string>((int x, int y, int z) => $"{x}-{y}-{z}");
Lợi ích tóm gọn
- ✅ Đọc hiểu code dễ dàng - tự tài liệu hóa (self-documenting).
- ✅ Tránh bug thứ tự tham số - đặc biệt khi nhiều params cùng kiểu.
- ✅ Linh hoạt - bỏ qua optional params giữa chừng.
- ✅ Refactor an toàn - đổi thứ tự parameter trong method không break call sites.