18

如果我有这样的课程:

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>();
    }
}

看到这两种方法在这种情况下都有效,使用其中一种方法有好处还是坏处?

是继承构造函数更高效并使代码执行得更快,还是有一个我不知道的缺点是让第二个实现更高效?

4

5 回答 5

28

让一个构造函数调用另一个构造函数的主要好处之一是您可以通过这种方式设置只读字段,而不能通过调用非构造函数方法来做到这一点。

例如:

public class Foo
{
    private readonly int myNumber;

    public Foo() : this(42)
    {
    }

    public Foo(int num)
    {
        myNumber = num;
    }
}

性能方面,调用另一个构造函数可能不会比调用另一个方法更有效率,但在我看来,构造函数调用另一个构造函数比调用一个单独的私有方法更具可读性,该方法的唯一目的是由构造函数调用。

当然,在某些情况下,有一个单独的方法是有意义的,而且它本身肯定不是“错误的”。在大多数情况下,链式构造函数对许多人来说读起来更好,并且不会对性能产生负面影响。

更新:我对每种方式执行了 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字段,并且在大多数情况下它更具可读性。

于 2012-05-31T17:21:56.303 回答
6

链接构造函数是强制执行 SRP 和程序流的好方法。Initialize()如果在对象生命周期中有其他情况您可能还想“初始化”它,那么将初始化代码隐藏在独立函数中可能是有意义的;也许如果您希望能够快速实例化和延迟初始化它。但是,如果在生命周期中执行该功能的唯一有效时间是在实例化期间,并且初始化是一组明确定义的离散步骤,需要按顺序执行,那么链接有助于实现这一点。

于 2012-05-31T17:23:21.043 回答
4

关键是减少重复代码的数量。在这种情况下,从参数化构造函数调用基本构造函数可以减少在忘记更新它们之后添加错误的机会。

于 2012-05-31T17:22:15.493 回答
3

拥有 Initialise() 函数的一个好处是,如果您想重置对象 - 您可以简单地再次调用 init 函数,而不是删除并重新创建对象。

于 2012-05-31T17:23:22.730 回答
3

我可能会因为这样说而被烧死,但在这种情况下我更喜欢使用默认参数:

public Foo(string parameter = null)
{

}

在我看来,我有 10 到 15 个可选参数并且有 15 个不同的构造函数并不是一个优雅的解决方案。我认为默认参数只是在 4.0 框架中重新引入。

于 2012-05-31T17:26:10.567 回答