2012-05-31 21 views
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>(); 
    } 
} 

看到无论是在这种情况下接近的工作,是有一个好处,或使用一个比其他优缺点?

继承constrcutors更有效率,并使代码执行更快或有一个缺点,我不知道如何使第二个实现更有效吗?

+1

我同时使用。如果把建设者连在一起是有道理的,我就这样做;但有时(例子没有想到)我已经用'InitializeFoo()'方法并从所有构造函数中调用它。 – Nate

+0

异常安全是我唯一担心的事情。 –

回答

28

让一个构造函数调用另一个构造函数的关键好处之一是您可以通过调用非构造函数方法来设置只读字段。

例如:

public class Foo 
{ 
    private readonly int myNumber; 

    public Foo() : this(42) 
    { 
    } 

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

在性能方面,它可能没有更多或更少的高效调用另一个构造比调用另一个方法,但它更具有可读性,在我看来,对于一个构造函数调用另一个构造函数比调用一个单独的私有方法的唯一点是由构造函数调用。

当然,有一种情况可能是单独的方法有意义,而且它本身并不是“错误的”。链接构造函数在大多数用途中读取更好,并且不会对性能产生负面影响。

更新:我进行的每路10,000,000迭代(链接VS私人初始化方法),结果是如此接近他们几乎没有区别:

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字段,并且在大多数情况下它更具可读性。

+0

非常感谢您的快速回复。我完全同意,这个和大多数设计descitions是情境,有时它只是更好的另一种方式。我主要关心的是性能,影响编译或执行时间。你很好地解决了这个问题,非常感谢。 – Nope

+2

随时!与其他任何东西一样,编写一个小测试并使用System.Diagnostics.Stopwatch()来测量每个数据的几百万次迭代真的很容易... –

+0

我们在工作中遇到了一个问题, ':this()'。我有点担心修复和可能的效率问题。我从来没有想过要写一个快速测试。感谢您指出了这一点。我肯定会试一试......下班后:)。 – Nope

4

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

+1

如果两个构造函数调用相同的'Init'方法,则此问题已解决。看来这就是OP将代码与之进行比较的原因。 – Servy

6

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

+0

我从来没有通过SRP,这是一个很好的观点。 – Nope

3

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

+2

+1。为什么初始化方法可能有用。注意我会尝试重新设计类以避免它 - 如果实例在多个其他对象之间共享,则可能需要提供协调代码来通知对象状态的这种重大变化。 –

+0

不错的一个。这在决定执行哪个实施时非常有用。谢谢。 – Nope

2

我可能会被灼伤这么说,但我更喜欢在这种情况下使用默认参数:

public Foo(string parameter = null) 
{ 

} 

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

相关问题