C# Object Instantiation: Part I - Constructors

Introduction

The first way we learned to approach object instantiation was with the constructor method in 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, we declare a constructor as follows.

public class One
{
    public One()
    {
        // Constructor code here
    }

    public int Number { get; set; } // This is a property, assuming you want to define a property named "Number"
}

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

OneobjOne=newOne();

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).

publicclassOne:Number{}

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

publicclassOne:Number
{
publicOne(){}
}

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.

The default constructor has no parameters, so as soon as we declare an input parameter requirement on the constructor, we lose the default constructor.

publicclassOne:Number
{
publicOne(intx){}
}

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

OneobjOne=newOne(3);

Accessor change in Object instantiation

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.

publicclassOne:Number
{
privateOne(){}
}

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
{
    private One()
    {
        // First private constructor
    }

    private One(int x)
    {
        // Second private constructor with a parameter '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.

OneobjOne=newOne(3);
OneobjOne=newOne();

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

Okay, 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
{
    private DateTime m_startDate;

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

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

Now we have a class 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
{
    private DateTime m_startDate;

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

    public Startup(DateTime startDate)
    {
        m_startDate = 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
{
    private DateTime m_startDate;

    // Master constructor: It sets all the values in the class
    public Startup(DateTime startDate)
    {
        m_startDate = 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.

publicStartup():this(DateTime.Now)
{
}

So now, our default constructor 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
{
    private DateTime m_startDate;

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

    // Default constructor: It calls the master constructor with DateTime.MinValue
    public Startup() : this(DateTime.MinValue)
    {
    }

    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.

To better understand the article, please go through the next parts.


Similar Articles