考虑以下类:
public class MyClass
{
public void MyMethod(int a, object b)
{
}
}
如果其他人这样称呼你的班级:
new MyClass().MyMethod(1, 1);
然后在您的程序集的未来版本中添加一个无辜的重载:
public class MyClass
{
public void MyMethod(int a, object b)
{
}
public void MyMethod(object a, int b)
{
}
}
其他人的代码不会针对新程序集进行编译。
你说得对,方法重载会带来问题……但它并不总是有问题。
假设一个简单的例子——你有一个方法在Type - T 上运行。如果您想添加一个方法重载来处理第二个Type U,请考虑T 和U 可能有哪些接口和基类(包括T 或U 相互扩展) .如果有一个常见的Type,请考虑在设计时将其设为参数类型(如果足够具体的话)。如果没有,那么您可能需要方法重载。一个很好的人为示例可能是返回数字平方的方法。对于具有* 运算符的Type 没有通用抽象(您可以在C# 中编写自己的)。因此,您必须使用 (2) 个方法来处理 int 和 double:
public int SquareMe(int x) { return x * x; }
public double SquareMe(double x) { return x * x; }
但是,如果您发现自己想要创建一个在 List<T>、IEnumerable<T> 和 T[] 上运行的方法,您最好编写该方法来接受 IEnumerable<T>(并且只需调用 @987654342 @ 立即在其上,以防止 IEnumerable 在您的代码多次需要它时多次扩展 - 如果您只是 foreach'ing 它一次,则无需扩展它)这样您就只剩下(1) 编写测试的方法。每种方法,特别是在公开使用的 API 上,都需要维护、记录、测试、自动化等。通常越简单越好(但复杂性也有它的位置)。很难给出一个设计 API 的算法(如果有这样的算法,我们可以将设计生成为某个假设程序的输出,是吗?)
在设计供公共使用的类和接口时,您应该非常小心方法重载(以及您的整个 API,一般来说 - 方法重载引入细微的破坏性更改只是需要考虑的一件事 - 几乎任何更改都可能是一个突破性的变化)。如果您的 API 被所有人(例如 Microsoft)使用,那么对 API 的所有更改都必须经过深思熟虑,并且至少有 0 个重大更改。
如果它是用于“内部”使用(并且您可以在构建时检测编译中断),那么如果编译器满意,方法重载本身就不应该是太大的交易。话虽如此 - 由于 C# 将选择什么,有人可能会意外调用不同的重载。使用直观(即主观上)与方法所做内容相匹配的显式方法名称(微软通常建议用 C# 拼写出来)可能比重载问题更重要。
与其他事物一样,这种语言特性是在显式和隐式之间进行权衡,以及它是否是一个好主意因情况而异;方法重载既可以使用也可以滥用。一般来说,在发展自己的风格之前,尝试学习一门新语言的现有实践、模式和文化,这样你就可以利用之前每个人的成功和失败。方法重载肯定在 C# 中占有一席之地。