ARTICLE

C# Object Instantiation: Part I. Constructors

Posted by Matthew Cochran Articles | C# Language June 24, 2007
There are many ways to approach object instantiation. In this article we'll cover a few of the patterns used to instantiate objects.
Reader Level:

Part I. Standard "New-Uping"

The first way we learned to approach object instantiation was with the constructor method on the class. This is the tried and true (and only) way to actually make an instance of a class.  The constructor is a method with no return type declared and has the same name as the class it is declared in.

Right about now you're probably already thinking "Hey wait a minute! What about the many approaches you mentioned?!?"  Well, all the different approaches are really just different ways to control where (and when) we new-up our objects and I'll get to these cool tricks in Part II after we cover the basics.

The Default Constructor

So, to get started, when we declare a constructor as follows:

public class One:Number
{
    public One() { }
}

We new-up (instantiate) the object using the constructor we defined:

One objOne = new One();

Every time we make a new instance of the "One" class, the constructor method will be run.  If there is actually code in the constructor, it will be executed on instantiation of the object.

When the following class is instantiated:

public class Number
{
    protected Number()
    {
        Console.WriteLine(GetType().ToString() + " built");
    }
}

We'll get a call to the constructor and output to the console.

With C#, if no constructor is defined, we get a default constructor by default.  This default constructor will have no parameters and will not do anything and essentially be the same as if we had declared an empty constructor so these two class declarations are equivalent.

No constructor defined (ends up the same as below):

public class One:Number{}

Default constructor defined (ends up the same as above):

public class One:Number
{
    public One() { }
}

Changing the Default Constructor

Also with C#, as soon as we declare a constructor with a signature different than the default constructor, we no longer get a default constructor like in the following two examples:

Input parameter change:  The default constructor has no parameters, so as soon as we declare an input parameter requirement on the constructor we loose the default constructor:           

public class One : Number
{
    public One(int x) { }
}

In this case we are now required to pass an integer on instantiation:

One objOne = new One(3);

Accessor change:  the default constructor is public, so as soon as we declare that the constructor is private to the "One" class, we can no longer instantiate the object from outside the class.  This probably seems strange right now, but we'll discuss how to use this in a bit.

public class One : Number
{
    private One() { }
}

Providing Multiple Constructors

We can provide multiple constructors, so if we want to have the choice of whether to supply a value to the constructor or not we'll just write two of them:

public class One : Number
{
    private One() { }
    private One(int x) { }
}

This will allow us to instantiate by passing nothing or passing an integer when we new-up the "One" class so the following two declarations are now valid:

One objOne = new One(3);
One objOne = new One();

Using Constructors

By now you're probably asking "Ok... Real nice constructors -n- all.  I get it.  But what's the point, really?"

The point of constructors is to provide any initialization that the class needs.  Let's say we have a property that tells us when the object was instantiated as in the following class.

public class Startup
{
    private DateTime m_startDate;

    public DateTime StartDate
    {
        get { return m_startDate; }
    }
}

Ok, that's all fine and good until we need to initialize the value to the time the object was actually instantiated.  To do this, we use the constructor:

public class Startup
{
    public Startup()
    {
        m_startDate = DateTime.Now;
    }

    private DateTime m_startDate;

    public DateTime StartDate
    {
        get { return m_startDate; }
    }
}

Now we have a class that where the value will be guaranteed to be initialized.;

Constructors Calling Constructors

If we use the previous example but want to be able to specify the start date, we can overload the constructor:

public class Startup
{
    public Startup()
    {
        m_startDate = DateTime.Now;
    }

    public Startup(DateTime startDate)
    {
        m_startDate = startDate;
    }

    private DateTime m_startDate;

    public DateTime StartDate
    {
        get { return m_startDate; }
    }
}

So now we can choose whether or not to specify the start date.  If we don't specify it in the constructor, we get the default which is DateTime.Now.

This works fine, but just to follow best practices and to keep our sanity when it comes to maintaining our code, we should specify one (and only one) constructor to be the "master" constructor where everything happens so if there are changes in one of the constructors we don't have to hunt down what is happening where.  The "master" constructor will be the one that sets all the member variables in the class:          

public class Startup
{
    // Master constructor:
    // It sets all the values in the class
    public Startup(DateTime startDate)
    {
        m_startDate = startDate;
    }

    private DateTime m_startDate;

    public DateTime StartDate
    {
        get { return m_startDate; }
    }
}

Now what we want to do is have all the other constructors call the "master" constructor.  The syntax for chaining our constructors is as follows:

    public Startup() : this(DateTime.Now)
    {
    }

So now, our default construtor will call our "master" constructor and pass the current date and time.  If we choose to change the default time in the default constructor we'll just update the value passed from the default constructor to the "master" constructor.  This may not seem like a big deal now, but if we have dozens of constructors on an object, it is a good way to organize them so we get consistent behavior and don't repeat code somewhere that we could miss updating.

public class Startup
{
    // Master constructor:
    // It sets all the values in the class
    public Startup(DateTime startDate)
    {
        m_startDate = startDate;
    }

    public Startup() : this(DateTime.MinValue) { }

    private DateTime m_startDate;

    public DateTime StartDate
    {
        get { return m_startDate; }
    }
}

Calling Constructors through the Inheritance Chain

The final thing we'll look at is calling constructor methods through the inheritance chain.

If we have a base class with a parameterized constructor

public abstract class Animal
{
    public Animal(string name)
    {
        m_name = name;
    }

    private string m_name;

    public string Name
    {
        get { return m_name; }
        set { m_name = value; }
    }
}

We can call the constructor through a derived class by using the base keyword. So in the following class the constructor's parameters are passed to the base constructor.

public class Cat : Animal
{
    public Cat(string name)
        : base(name)
    { }
}

Well, that's pretty much it for the constructor and the main way to "new-up" objects.  In the next article we'll look at different patterns for controlling the instantiation of our classes.

Until next time,
Happy coding

COMMENT USING