[C#] Object Initialization

It is the constructor of a class that is responsible to initialize the object’s field values. Though, the title of this article is not “Constructors” because C# provides another way to initialize objects.

 

1. Default Constructor

Actually, you do not need to provide any constructor to your custom classes. In such a case, the compiler will create a bare-minimum  constructor for you. This is called a default constructor.

The default constructor does not accept any parameters and initializes all fields with its default values (0, false, null, …)

public class Car
{
  string modelName;
  int currentSpeed;
}

Car myCar = new Car(); // works using the default constructor

 

2. Custom Constructors

You can create as many overloaded constructors as you want. A constructor is a special method that does not return a value and has the same name as the class.

public class Car
{
  string modelName;
  int currentSpeed;

  public Car(string name, int speed)
  {
    modelName = name;
    currentSpeed = speed;
  }
}

Car myCar = new Car();

Looks good, right? Wrong. You will get an compile time error: ” ‘Car’ does not contain a constructor that takes 0 arguments.

What’s wrong here?

When you provide custom constructors (even 1), the compiler won’t give you the free default constructor. The default constructor is created only when you do not provide ANY constructor. So when you need to create a custom constructor, you need to create a default version too.

public class Car
{
  string modelName;
  int currentSpeed;

  public Car()
  {
    modelName = "N/A";
    currentSpeed = 0;
  }

  public Car(string name, int speed)
  {
    modelName = name;
    currentSpeed = speed;
  }
}

 

3. Chaining Constructor Calls

You can call another constructor from a constructor using the “this” keyword. It is called “Constructor chaining“.

Usually, each constructor’s initialization logic is very alike. So there might be some repeated code statements. By calling the most  specific constructor (master constructor), you can use only one set of initialization code.

The “Car” class can be written again.

public class Car
{
  string modelName;
  int currentSpeed;

  public Car() : this ("N/A", 0)
  { }

  public Car(string name) : this (name, 0)
  { }

  public Car(int speed) : this ("N/A", speed)
  { }

  public Car(string name, int speed)
  {
    modelName = name;
    currentSpeed = speed;
  }
}

 

4. Execution Flow of Chaining Constructors

Let’s find out which constructor is executed first when constructors are chained.

public class Car
{
  string modelName;
  int currentSpeed;

  public Car() : this ("N/A", 0)
  {
    Console.WriteLine("Car()");
  }
  public Car(string name, int speed)
  {
    modelName = name;
    currentSpeed = speed;
    Console.WriteLine("Car(string name, int speed)");
  }
}

Car myCar = new Car();

The output is:

Car(string name, int speed)
Car()

As you can see at the result, the master constructor is called before the less specific constructor.

The more correct flow is like this:

  1. Go to the constructor you called in the code
  2. Check whether there is a chained constructor. If the master constructor exists, the master constructor is called.
  3. The initialization code in the master constructor is executed
  4. The execution point moves back to the original constructor
  5. The code in the original constructor is executed.

 

5. Execution Flow of Constructors in the Inheritance Hierarchy

When you create an instance of a class, it calls all constructors in the inheritance hierarchy. Which one will be executed first? Base class  or subclass? Let’s find out.

public class Car
{
  public Car()
  {
    Console.WriteLine("Car()");
  }
}

public class SportsCar : Car
{
  public SportsCar ()
  {
    Console.WriteLine("SportsCar()");
  }
}

SportsCar myCar = new SportsCar();

The output is:

Car()
SportsCar()

Well, the base class’s constructor is called first. This behavior makes sense. This behavior redefines the initial state of the base class’s fields in the subclass’s constructor.

 

6. Calling the Specific Version of the Constructor in a Base class

When the constructors are chained, the “this” keyword is used. To call the specific version of the base class’s constructor, you can use  the “base” keyword. By default, the parameter-less version is called.

public class SportsCar : Car
{
  public SportsCar() : base ("N/A", 0)
  {
  }
}

 

7. Static Constructors

Where do you want to initialize static fields? The best place would be where the static field is defined if you know the initial value. But you do not always know the value at compile time. What if you need to set the value at runtime?

Look at the following “BankAccount” class.

public class BankAccount
{
  static double interestRate;
  ...
}

You want to share the same interest rate for all BankAccount objects. It makes sense to declare the interestRate field as static. The  problem is that you need to read the interest rate from the DB.

The first option is that you can initialize the interest rate in constructors.

public BankAccount()
{
  interestRate = readRateFromDB();
}

This approach works. But whenever a bank object is created, the rate is re-initialized even though the value is the same. Moreover, it needs to access DB unnecessarily.

The solution is a “static constructor“. The “static” keyword is used to create a static constructor.

  • A class (or structure) may define only a single static constructor
  • A static constructor does not take access modifiers or have parameters
  • A static constructor is called automatically and only once to initialize the class before the first instance is created or any static  members are referenced
  • A static constructor executes before any instance-level constructors
  • A static constructor cannot be called directly.
public class BankAccount
{
  static double interestRate;

  static BankAccount()
  {
    interestRate = readRateFromDB();
  }
}

 

8. Destructors (?)

C++ allows you to define destructors. The destructors in the inheritance hierarchy are executed in a reverse order (from the subclass to  the base class).

How about C#? Does C# have destructors?

Yes, you can define destructors in C#.

public class Car
{
  ~Car()
  {
    ...
  }
}
  • Destructors cannot be defined in structs
  • A class can only have one destructor (cannot be overloaded)
  • Destructors cannot be inherited
  • Destructors may not be called directly. They are invoked automatically by GC(Garbage Collector)
  • A destructor does not take modifiers or have parameters.

The baseline is that you do not use destructors in C# in almost all cases. The only situation you can used a destructor is to release  external resources. But even in the case, you want to release the expensive external resources, you need to use the “IDisposable”  interface rather than a destructor.

The “IDisposable” interface let you release resources before GC can clean up the objects.

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s