Method Overloading cho phép nhiều phương thức cùng tên nhưng khác signature (số lượng, kiểu, thứ tự tham số) trong cùng một class/struct. Đây là dạng Compile-time Polymorphism.
2 cách tạo overload
- Khác số lượng tham số
- Khác kiểu dữ liệu tham số
KHÔNG tạo overload chỉ khác: kiểu trả về, tên tham số, modifier (ref/out - trừ khi signature khác).
Ví dụ: Khác số lượng tham số
using System;
public class Calculator
{
public int Mul(int a, int b) => a * b;
public int Mul(int a, int b, int c) => a * b * c;
public int Mul(int a, int b, int c, int d) => a * b * c * d;
// C# 4.0+: Optional parameters thay thế overload đơn giản
public int MulOpt(int a, int b, int c = 1, int d = 1) => a * b * c * d;
}
class Program
{
static void Main()
{
Calculator calc = new Calculator();
Console.WriteLine($"2 params: {calc.Mul(10, 15)}"); // 150
Console.WriteLine($"3 params: {calc.Mul(8, 13, 20)}"); // 2080
Console.WriteLine($"4 params: {calc.Mul(3, 7, 10, 7)}"); // 1470
// Optional params
Console.WriteLine($"Optional 3: {calc.MulOpt(2, 3, 4)}"); // 24 (d=1)
}
}
Ví dụ: Khác kiểu dữ liệu
public class Printer
{
public void Print(int i) => Console.WriteLine($"Int: {i}");
public void Print(double d) => Console.WriteLine($"Double: {d}");
public void Print(string s) => Console.WriteLine($"String: {s}");
public void Print(bool b) => Console.WriteLine($"Bool: {b}");
public void Print(int[] arr) => Console.WriteLine($"Array: [{string.Join(", ", arr)}]");
}
Overload Resolution (Quy tắc chọn overload)
- Exact match (khớp chính xác kiểu).
- Implicit conversion (widening: int→long→float→double, derived→base).
- Params array (ưu tiên thấp hơn fixed params).
- Non-generic > Generic (nếu signature giống nhau).
void Foo(int x) { }
void Foo(double x) { }
void Foo(object x) { }
Foo(5); // Foo(int) - exact
Foo(5L); // Foo(long) - exact (nếu có) else Foo(double) - implicit int→long→double
Foo("test"); // Foo(object) - implicit string→object
Best Practices
- Dùng Optional Parameters (C# 4+) thay vì overload cho tham số tùy chọn:
void Foo(int a, int b = 0). - Dùng Named Arguments để rõ ràng:
Foo(a: 1, c: 3). - Tránh overload gây ambiguous:
Foo(int)vàFoo(double)gọiFoo(5)chọn int. - XML Doc cho từng overload:
///.
So sánh Overloading vs Overriding
| Đặc điểm | Overloading (Nạp chồng) | Overriding (Ghi đè) |
|---|---|---|
| Mối quan hệ | Cùng class | Base ↔ Derived class |
| Signature | Phải khác | Phải giống hệt |
| Binding | Static (Compile-time) | Dynamic (Runtime) |
| Từ khóa | Không cần | virtual/override |
| Mục đích | Cùng tên, hành vi khác cho input khác | Thay đổi hành vi cho cùng input |