Nope
Nope

Reputation: 22339

Is there a benefit or drawback when one constructor implements another?

If I have a class like this:

public class Foo
{
    public IEnumerable<Bar> Bars { get; set; }

    public Foo()
    {
        Bars = new List<Bar>();
    }
}

At some stage I re-factor the class and add a secondary constructor which implements the first one like this:

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
    }
}

I could have also written it similar to this:

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

Seeing both approaches work in this scenario, is there a benefit or drawback in using one over the other?

Is inheriting constrcutors more efficient and making that code execute faster or is there a drawback which I don't know about making the second implementation more efficient instead?

Upvotes: 18

Views: 2258

Answers (5)

James Michael Hare
James Michael Hare

Reputation: 38397

One of the key benefits in having one constructor call another constructor is that you can set read-only fields that way, you can't do that by calling a non-constructor method.

For example:

public class Foo
{
    private readonly int myNumber;

    public Foo() : this(42)
    {
    }

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

Performance wise, it's probably no more or less efficient to call another constructor than to call another method, but it is more readable, in my opinion, for a constructor to call another constructor than to call a separate, private method whose only point is to be called by a constructor.

There could, of course, be situations when having a separate method makes sense, and it's certainly not "wrong" per se. Chaining constructors just reads better to many for most uses, and there is no negative performance impact.

UPDATE: I performed 10,000,000 iterations of each way (chained vs private initialization method) and the results were so close they were nearly indistinguishable:

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.

So really, performance-wise there is nearly no benefit either way. The main benefit is with chained constructors you can set readonly fields, and in most cases it is more readable.

Upvotes: 28

Cole W
Cole W

Reputation: 15303

I may get burned for saying this but I prefer using default parameters in this case:

public Foo(string parameter = null)
{

}

I've had cases where I had 10 - 15 optional parameters and having 15 different constructors wasn't an elegant solution in my opinion. I think default parameters were only reintroduced in the 4.0 framework though.

Upvotes: 3

Luke
Luke

Reputation: 560

A benefit of having an Initialise() function is in case you would like to reset your object - you can simply call the init function again rather than delete & recreate the object.

Upvotes: 3

Rex M
Rex M

Reputation: 144122

Chaining constructors is a good way to enforce SRP and program flow. Hiding initialization code inside a standalone Initialize() function could make sense if there are other situations in the object lifecycle where you might also want to "Initialize" it; perhaps if you wanted to be able to quickly instantiate and lazy-initialize it. But if the only valid time in the lifecycle to execute that functionality is during instantiation, and initialization is a well-defined set of discrete steps that need to be taken in order, then chaining facilitates that.

Upvotes: 6

Matt Beckman
Matt Beckman

Reputation: 5012

The key is to reduce the amount of duplicate code. In this case, calling the base constructor from a parameterized constructor reduces the chances of adding a bug later on after forgetting to update both of them.

Upvotes: 4

Related Questions