如果我有这样的课程:
public class Foo
{
public IEnumerable<Bar> Bars { get; set; }
public Foo()
{
Bars = new List<Bar>();
}
}
在某个阶段,我重新考虑了这个类并添加了一个辅助构造函数,它实现了第一个这样的构造函数:
public class Foo
{
public IEnumerable<Bar> Bars { get; set; }
// some more properties were added
public Foo()
{
Bars = new List<Bar>();
}
public Foo(string parameter): this()
{
.... some code here
}
}
我本可以写出类似的内容:
public class Foo
{
public IEnumerable<Bar> Bars { get; set; }
// some more properties were added too
public Foo()
{
InitilizeFoo();
}
public Foo(string parameter)
{
InitilizeFoo();
.... some code here
}
private void InitializeFoo()
{
Bars = new List<Bar>();
}
}
看到这两种方法在这种情况下都有效,使用一种方法有没有好处或缺点?
继承constrcutors是否更有效率并使代码执行得更快或者是否存在我不知道如何使第二个实现更高效的缺点?
答案 0 :(得分:28)
让一个构造函数调用另一个构造函数的一个主要好处是,您可以设置只读字段,不能通过调用非构造函数方法来实现。
例如:
public class Foo
{
private readonly int myNumber;
public Foo() : this(42)
{
}
public Foo(int num)
{
myNumber = num;
}
}
性能方面,调用另一个构造函数调用另一个方法的效率可能不高或低,但在我看来,构造函数调用另一个构造函数比调用一个单独的私有方法更具可读性。 point将由构造函数调用。
当然,当有一个单独的方法是有道理的时候,它本身肯定不是“错误的”。对于大多数用途而言,链接构造函数对于许多用户来说效果更好,并且没有负面的性能影响。
UPDATE :我执行了10,000,000次迭代(链式与私有初始化方法),结果非常接近,几乎无法区分:
Initializer Method took: 84 ms for 10,000,000 iterations, 8.4E-06 ms/each.
Chained Constructors took: 81 ms for 10,000,000 iterations, 8.1E-06 ms/each.
所以,从表现来看,无论如何都几乎没有任何好处。主要的好处是使用链式构造函数,您可以设置readonly
个字段,并且在大多数情况下它更具可读性。
答案 1 :(得分:6)
链接构造函数是强制执行SRP和程序流的好方法。如果在对象生命周期中还有其他情况你可能也想要“初始化”它,那么在独立的Initialize()
函数中隐藏初始化代码是有意义的。也许如果你想能够快速实例化和懒惰初始化它。但是,如果生命周期中执行该功能的唯一有效时间是在实例化期间,并且初始化是一组明确定义的离散步骤,需要按顺序进行,那么链接可以促进这一点。
答案 2 :(得分:4)
关键是减少重复代码的数量。在这种情况下,从参数化构造函数中调用基础构造函数会在忘记更新这两个构造函数之后减少添加错误的可能性。
答案 3 :(得分:3)
使用Initialise()函数的好处是你想要重置你的对象 - 你可以简单地再次调用init函数而不是删除&amp;重新创建对象。
答案 4 :(得分:2)
我可能因为这样说而被烧伤但我更喜欢在这种情况下使用默认参数:
public Foo(string parameter = null)
{
}
在我看来,我有10到15个可选参数的情况,并且有15个不同的构造函数在我看来并不是一个优雅的解决方案。我认为默认参数只是在4.0框架中重新引入。