有两种方法可以实现重载.第一个是在一个方法/构造函数中执行所有操作,并从其他重载调用它,这会导致更长的方法体.第二个是在每个重载中做最小的,因此有时难以导航代码并且理解哪个重载做了什么.
例如,如果Cat类的两个重载是:
public Cat(string name,int? weight,Color mainColor); public Cat(string name);
有两种方法可以实现这个:
第一种
public Cat(string name,Color mainColor) { // Initialize everything. this.name = name; if (weight.HasValue) this.weight = weight.Value; // There is a bug here (see the anwer of @Timwi): mainColor can be null. this.colors = new List<Colors>(new[] { mainColor }); } public Cat(string name) : this(name,null,null) { // Nothing else to do: everything is done in the overload. }
第二种
public Cat(string name) { // Initialize the minimum. this.name = name; this.colors = new List<Colors>(); } public Cat(string name,Color mainColor) : this(name) { // Do the remaining work,not done in the overload. if (weight.HasValue) this.weight = weight.Value; this.colors.Add(mainColor); }
问题
>如何调用这两种类型的重载(能够在互联网或书籍中查找更多信息)?
>在这些类型之间进行选择时,必须考虑的主要问题/因素是什么?
注意:由于C#4.0允许您指定可选参数,为避免歧义,假设我只是在讨论C#3.0.
解决方法
我认为这是另一个例子,其中没有一个单一的,教条的答案将合理地涵盖所有案例.我会一直关注个案,并根据所有可用因素做出决定.
一个因素是第一个有很多ifs.您的代码也有一个错误:您将在颜色列表中添加空值;为了修复这个bug,你需要更多的ifs.这样的构造函数很容易变得混乱.无数的ifs表明存在几种逻辑大不相同的情况,因此对于每种情况都有单独的构造函数是完全有意义的.
但是,在没有那么多ifs的情况下,逻辑对于所有人都是相同的,所以现在调用一个构造函数来执行那个逻辑是有意义的,并且做得很好.然后只有一个地方可以维护它.
另一个因素是,在您的示例中,第一个因素是未初始化的重量.这不一定是坏事,因为幸运的是,C#中的默认初始化是可预测的;但是如果权重的字段声明将其初始化为非零值并且只有一些构造函数用另一个值覆盖该默认值,我会认为它是不好的形式.构造函数参数和/或this(…)调用是记录该字段的默认值的更好位置. (最好是构造函数参数,因为这样即使是客户端程序员也可以看到默认值,但显然需要C#4.)当然,也可以使用字段初始化器初始化所有字段并将构造函数保留为空,如果你只有一个没有参数的构造函数,这是一个合理的策略.
所以是的,就像你说的那样,你不希望方法体太长,但你也不希望代码太难以导航,所以你需要在任何给定的情况下在两者之间取得平衡.