是的,重载很容易被过度使用。
我发现确定是否需要重载的关键是考虑受众——不是编译器,而是维护程序员,他们将在数周/数月/数年内出现并且必须了解代码是什么试图达到。
像 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# 或尚未发明的全新的东西编写的。可能是该语言不支持重载。