是的,重载很容易被过度使用。
我发现,确定重载是否值得的关键是考虑受众 - 不是编译器,而是维护程序员,他们将在几周/几个月/几年内出现,并且必须了解代码试图实现的目标。
像GetProducts()这样的简单方法名称是清晰易懂的,但它确实留下了很多未说的。
在许多情况下,如果传递给 GetProducts() 的参数命名良好,维护人员将能够计算出重载的作用 - 但这依赖于在使用点的良好命名规则,这是无法强制执行的。您可以强制执行的是它们所调用的方法的名称。
我遵循的准则是,如果方法可互换,则仅重载它们 - 如果它们执行相同的操作。这样,我就不介意我的类的使用者调用哪个版本,因为它们是等效的。
为了说明这一点,我很乐意对 DeleteFile() 方法使用重载:
void DeleteFile(string filePath);
void DeleteFile(FileInfo file);
void DeleteFile(DirectoryInfo directory, string fileName);
但是,对于您的示例,我将使用单独的名称:
public IList<Product> GetProductById(int productId) {...}
public IList<Product> GetProductByCategory(Category category) {...}
public IList<Product> GetProductByName(string Name ) {...}
拥有全名使代码对维护人员(很可能是我)更加明确。它避免了签名冲突的问题:
// No collisions, even though both methods take int parameters
public IList<Employee> GetEmployeesBySupervisor(int supervisorId);
public IList<Employee> GetEmployeesByDepartment(int departmentId);
还有机会为每个目的引入重载:
// Examples for GetEmployees
public IList<Employee> GetEmployeesBySupervisor(int supervisorId);
public IList<Employee> GetEmployeesBySupervisor(Supervisor supervisor);
public IList<Employee> GetEmployeesBySupervisor(Person supervisor);
public IList<Employee> GetEmployeesByDepartment(int departmentId);
public IList<Employee> GetEmployeesByDepartment(Department department);
// Examples for GetProduct
public IList<Product> GetProductById(int productId) {...}
public IList<Product> GetProductById(params int[] productId) {...}
public IList<Product> GetProductByCategory(Category category) {...}
public IList<Product> GetProductByCategory(IEnumerable<Category> category) {...}
public IList<Product> GetProductByCategory(params Category[] category) {...}
代码的读取量比编写的要多得多 - 即使您在最初签入到源代码管理后再也回不来过代码,在编写下面的代码时,您仍然会将这行代码读取几十次。
最后,除非你正在编写一次性代码,否则你需要允许其他人从其他语言调用你的代码。似乎大多数业务系统最终都停留在生产中,远远超过了它们的使用日期。可能是在 2016 年使用你的类的代码最终被写成 VB.NET、C# 6.0、F# 或尚未发明的全新内容。可能是该语言不支持重载。