Introduction to Constructors

Introduction to the Constructor of a Class

When you create an object (a variable declared from a class), you are in fact describing an object. In some cases, you may want that object to hold some default characteristics so that you don't have to work from scratch. A constructor is a special method that specifies the primary information of an object.

ApplicationPractical Learning: Introducing Constructors

  1. Start Microsoft Visual Studio and Create a new Console App named Quadrilaterals2 that supports .NET 7.0 (Standard Term Support)
  2. To create a new folder, in the Solution Explorer, right-click Quadrilaterals2 -> Add -> New Folder
  3. Type Models as the name of the folder
  4. To create a class, in the Solution Explorer, right-click Models -> Add -> Class...
  5. Chang the file Name to Square
  6. Click Add
  7. From what we learned already, create a class as follows:
    namespace Quadrilaterals2.Models
    {
        public class Square
        {
        	private double s;
    
    	public double Side
        	{
                get => s;
                set => s = value;
            }
    
            public double Perimeter
            {
                get => s * 4;
            }
    
            public double Area
            {
                get => s * s;
            }
        }
    }

Creating a Constructor

A constructor is created as a special method with two main rules and one primary feature:

Here is an example of creating a constructor in a class named Square:

class Square
{
    Square()
    {
    }
}

Remember that any method that doesn't have an access level is considered private. This is also valid for constructors. Although you can have private constructors in very extreme scenarios, most of the constructors you will create or use must be public (or internal). Here is an example:

class Square
{
    public Square()
    {
    }
}

As we saw in the previous lessons, a class can have various types of members (such as fields, properties, and methods). Here is an example of a class that has some fields and a constructor:

class House
{
    public House()
    {
    }

    public string type;
    public int    beds;
    public double value;
}

In the body of a class, the order of appearance of the members is not important. This means that you can first create a constructor followed by other members, first the members and a constructor last, or a constructor between members. Here is an example:

public class House
{
    public int propNumber;
    public double baths;

    public House()
    {
    }

    public string type
    public int    beds;
    public double value;
}

A Constructor with a Parameter

In your class, you can create a constructor that uses a parameter. Here is an example:

public class Square
{
    public Square(double side)
    {

    }
}

In the body of the class, you can ignore or use the parameter. One way you can use it is to pass its value to a member variable of the class. Here is an example:

public class Square
{
    private double s;

    public Square(double side)
    {
        s = side;
    }
}

Remember that the other members, such as methods, of the class can access any member of the same class. After creating the class, you can declare variables of it.

Creating an Object

Calling a Constructor

From our introductions, we know that, when declaring a variable of a class type, after the new operator, you must write the name of the class followed by parentheses. Here is an example we saw already:

House residence = new House();

public class House
{
    public string type;
    public int beds;
    public double value;
}

In reality, when you declare a variable like that, you are actually calling the constructor of the class. As a result, the primary role of a constructor is to provide the default characteristics of an object created from a class. Therefore, in the body of a constructor, you can access each field and assign the desired value to it. Here is an example:

class House
{
    public string type;
    public int beds;
    public double value;

    public House()
    {
        type = "Single-Family";
        beds = 5;
        value = 495_680;
    }
}

ApplicationPractical Learning: Introducing Constructors

  1. To add a constructor, change the class as follows:
    namespace Quadrilaterals2.Models
    {
        public class Square
        {
            private double s;
    
            public Square(double side)
            {
                s = side;
            }
    
            public double Side
            {
                get => s;
                set => s = value;
            }
    
            public double Perimeter
            {
                get => s * 4;
            }
    
            public double Area
            {
                get => s * s;
    	}
        }
    }
  2. In the Solution Explorer, right-click Program.cs and click Rename
  3. Type Geometry (to get Geometry.cs)
  4. Press Enter
  5. Read the text of the message box and click Yes
  6. In the Solution Explorer, double-click Geometry.cs to access the main document of the project
  7. Change the document as follows:
    using Quadrilaterals2.Models;
    using static System.Console;
    
    WriteLine("=====================================");
    WriteLine("Enter the value to process the square");
    Write("Side:      ");
    double side = double.Parse(ReadLine());
    
    Square sqr = new Square(side);
    
    WriteLine("=====================================");
    WriteLine("Geometry - Square Summary");
    WriteLine("-------------------------------------");
    WriteLine("Perimeter: {0}", sqr.Perimeter);
    WriteLine("Area:      {0}", sqr.Area);
    Write("=====================================");
  8. To execute the application to test it, on the main menu, click Debug -> Start Without Debugging
  9. When requested, type the Side as 248.73 and press Enter
    =====================================
    Enter the value to process the square
    Side:      248.73
    =====================================
    Geometry - Square Summary
    -------------------------------------
    Perimeter: 994.92
    Area:      61866.61289999999
    =====================================
    
    Press any key to close this window . . .
  10. Press Enter to close the window and return to your programming environment
  11. To start a new project, on the main menu, click File -> New -> Project...
  12. Make sure Console App is selected and click Next
  13. Change the project Name to Chemistry1 and accept or change the project Location
  14. Click Next
  15. Make sure the Framework combo box is displaying .NET 7.0 (Standard Term Suppport).
    Click Create
  16. To create a new folder, in the Solution Explorer, right-click ElementaryAlgebra1 -> Add -> New Folder
  17. Type Models as the name of the folder
  18. In the Solution Explorer, right-click Models -> Add -> Class...
  19. Change the file Name to Element
  20. Press Enter
  21. Change the document and the class as follows:
    namespace Chemistry1.Models
    {
        public class Element
        {
        	internal string Symbol       { get; set; }
            internal string ElementName  { get; set; }
            internal int    AtomicNumber { get; set; }
            internal double AtomicWeight { get; set; }
        }
    }

An Object Without a Constructor

There are various ways to create an object. The most classic way is to start with the name of a class, assign the new operator followed by the name of the class again. Here is an example:

using static System.Console;

Trapezoid trap = new Trapezoid();

trap.Bottom = 1159.73;
trap.Top    = 736.86;
trap.Height = 552.94;

WriteLine("===========================");
WriteLine("Trapezoid");
WriteLine("---------------------------");
WriteLine("Top:    {0}", trap.Top);
WriteLine("Bottom: {0}", trap.Bottom);
WriteLine("Height: {0}", trap.Height);
WriteLine("---------------------------");
WriteLine("Area:   {0}", trap.Area);
Write("===========================");

public class Trapezoid
{
    private double _top_;

    public double Bottom { get; set; }
    public double Height { get; set; }

    public Trapezoid()
    {
        Bottom = 0.00;
        Height = 0.00;
    }

    public double Top
    {
        get
        {
            if (_top_ == 0.00)
                return Bottom * .75;

            return _top_;
        }
        set
        {
            _top_ = value;
        }
    }

    public double Area
    {
        get
        {
            return ((Bottom + Top) / 2.00) * Height;
        }
    }
}

This would produce:

===========================
Trapezoid
---------------------------
Top:    736.86
Bottom: 1159.73
Height: 552.94
---------------------------
Area:   524350.2373
===========================

Press any key to close this window . . .

When you use this technique, you can omit the constructor on the right side of the assignment operator. Here is an example:

using static System.Console;

Trapezoid trap = new();

// . . .

public class Trapezoid
{
    // . . .
}

A Variable Object

When you are creating an object, you can omit the constructor on the left side of the assignment operator. In this case, you can replace the constructor with the var keyword. Also in this case, you must use the constructor on the right side of the assignment operator. Besides the var operator, you can also use the dynamic keyword. Here are examples:

using static System.Console;

// A variable object
var trap = new Trapezoid();
// A dynamic object
dynamic zoid = new Trapezoid();

trap.Bottom = 1159.73;
trap.Top    = 736.86;
trap.Height = 552.94;

zoid.Bottom = 318.67;
zoid.Top = 526.36;
zoid.Height = 705.71;

WriteLine("===========================");
WriteLine("Trapezoid");
WriteLine("---------------------------");
WriteLine("Top:    {0}", trap.Top);
WriteLine("Bottom: {0}", trap.Bottom);
WriteLine("Height: {0}", trap.Height);
WriteLine("---------------------------");
WriteLine("Area:   {0}", trap.Area);
WriteLine("===========================");
WriteLine("Trapezoid");
WriteLine("---------------------------");
WriteLine("Top:    {0}", zoid.Top);
WriteLine("Bottom: {0}", zoid.Bottom);
WriteLine("Height: {0}", zoid.Height);
WriteLine("---------------------------");
WriteLine("Area:   {0}", zoid.Area);
Write("===========================");

public class Trapezoid
{
    private double _top_;

    public double Bottom { get; set; }
    public double Height { get; set; }

    public Trapezoid()
    {
        Bottom = 0.00;
        Height = 0.00;
    }

    public double Top
    {
        get
        {
            return (_top_ == 0.00) ? Bottom * .75 : _top_;
        }
        set { _top_ = value; }
    }

    public double Area
    {
        get => ((Bottom + Top) / 2.00) * Height;
    }
}

This would produce:

===========================
Trapezoid
---------------------------
Top:    736.86
Bottom: 1159.73
Height: 552.94
---------------------------
Area:   524350.2373
===========================
Trapezoid
---------------------------
Top:    526.36
Bottom: 318.67
Height: 705.71
---------------------------
Area:   298173.06065
===========================

Press any key to close this window . . .

Introduction to Constructors and Properties

Initializing a Property Reader

A read property is referred to as read-only property because the clients of the class can only retrieve the value of the property but they cannot change it. Therefore, if you create a read property, you should provide the users with the ability to primarily specify the value of the field it represents. This would be a way to initialize the property readers.

To initialize a property reader, you can use a constructor of the class. To start, when creating the constructor, add a parameter to it. The parameter must be the same type as the property you want to initialize. Then, in the body of the constructor, assign the parameter to the private field associated with the property. This can be done as follows:

public class Square
{
    private double _side;

    public double Side
    {
        get
        {
            return this._side;
        }
    }

    public Square(double s)
    {
        this._side = s;
    }
}

Once a read property has been created, other classes can access it, for example they can read its value.

Initializing an Automatic Read-Only Property

Remember that an automatic property is one that is created with only the get or set contextual keyword without a body. An automatic read-only property is a property created with the get constextual keyword without a body Here is an example:

public class Employee
{
    public string FullName { get; }
}

If you want to initialize an automatic read-only property, create a constructor. In the body of a constructor, assign the desired value to the property. Here is an example:

using static System.Console;

Employee staff = new();

Write("Employee: ");
WriteLine(staff.FullName);
Write("=================================");

public class Employee
{
    public string FullName { get; }

    public Employee()
    {
        FullName = "Julius Nyerere";
    }
}

You cannot use a function or a method other than a constructor to initialize an automatic read-only property. As an alternative, to initialize an automatic read-only property, instead of using a constructor, after the curly brackets of the property, assign the desired default value. Here is an example:

public class Depreciation
{
    public double Cost { get; } = 10000;
}

Initializing an Automatic Property

To initialize an automatic property, you can create a constructor that uses a parameter for the property. In the body of the constructor, assign the argument to the property. Here is an example:

public class Element
{
    public int AtomicNumber { get; set; }

    public Element(int number)
    {
        AtomicNumber = number;
    }
}

In the same way, if you want the property to be initialized with any value of your choice, you don't have to include a corresponding value in the constructor. Instead, in the body of the constructor, you can assign any value you want. Here is an example:

public class Element
{
    public int AtomicNumber { get; set; }

    public Element()
    {
        AtomicNumber = 12;
    }
}

ApplicationPractical Learning: Initializing Automatic Properties

  1. To initialize some automatic properties, change the Element class as follows:
    namespace Chemistry1.Models
    {
        public class Element
        {
            internal string Symbol       { get; set; }
            internal string ElementName  { get; set; }
            internal int    AtomicNumber { get; set; }
            internal double AtomicWeight { get; set; }
    
            public Element()
            {
                Symbol = "H";
                ElementName = "Hydrogen";
                AtomicNumber = 1;
                AtomicWeight = 1.008;
            }
        }
    }
  2. In the Solution Explorer, right-click Program.cs -> Rename
  3. Type PeriodicTable (to get PeriodicTable.cs) and press Enter
  4. Read the content of the message box and click Yes
  5. Click the PeriodicTable.cs tab and change the document as follows:
    using Chemistry1.Models;
    using static System.Console;
    
    Element elm = new Element();
    
    WriteLine("Chemistry");
    WriteLine("------------------------");
    WriteLine("Symbol:        " + elm.Symbol);
    WriteLine($"Atomic Number: {elm.AtomicNumber}");
    WriteLine("Element Name:  " + elm.ElementName);
    WriteLine($"Atomic Weight: " + elm.AtomicWeight);
    Write("========================");
  6. To execute the application, press Ctrl + F5
    Chemistry
    ------------------------
    Symbol:        H
    Atomic Number: 1
    Element Name:  Hydrogen
    Atomic Weight: 1.008
    ========================
    
    Press any key to close this window . . .
  7. Press U to close the window and return to your programming environment

Assigning a Default Value to an Automatic Property

Instead of initializing an automatic property in a constructor, you can assign the desired value after the curly brackets of the property. Here is an example:

public class Element
{
    public int AtomicNumber { get; set; } = 12;
}

ApplicationPractical Learning: Automatically Initializing Properties

  1. Click the Element.cs tab to access its class
  2. To provide some default values to the automatic properties, change the class as follows:
    namespace Chemistry1.Models
    {
        public class Element
        {
            internal string Symbol       { get; set; } = "He";
            internal string ElementName  { get; set; }span class="codered">= "Helium"span>
            internal int    AtomicNumber { get; set; } = 2;
            internal double AtomicWeight { get; set; } = 4.002602;
        }
    }
  3. To execute the project, press Ctrl + F5:
    Chemistry
    ------------------------
    Symbol:        He
    Atomic Number: 2
    Element Name:  Helium
    Atomic Weight: 4.002602
    ========================
    
    Press any key to close this window . . .
  4. Close the form and return to your programming environment

A Required Initialized Property

Introduction

Consider a read-only property as follows:

using static System.Console;

House residence = new();

WriteLine($"Market Value: {residence.MarketValue}");

public class House
{
    int price;

    public int MarketValue
    {
        get
        {
            return price;
        }
    }
}

Obviously, this read-only property is not initialized, and there is no way to initialize the property. Of course, the alternative is to add a set clause and be able to initialize the property from there. Here is an example:

using static System.Console;

House residence = new();

WriteLine($"Market Value: {residence.MarketValue}");

public class House
{
    int price;

    public int MarketValue
    {
        get
        {
            return price;
        }

        set
        {
            price = value;
        }
    }
}

Notice that the above code makes it possible to initialize the property, but the property was not used without being initialized. Of course, now that the property has a set clause, you can initialize it. Here is an example:

using static System.Console;

House residence = new House();
residence.MarketValue = 450_000;

public class House
{
    int price;

    public int MarketValue
    {
        get
        {
            return price;
        }

        set
        {
            price = value;
        }
    }
}

WriteLine($"Market Value: {residence.MarketValue}");

If the property was not initialized, this means that if you did not, or forgot to, initialize the property, or you made a mistake of using or accessing a property that was not initialized, your code could lead to unpredictable behavior. There is an alternate or a solution to this type of situation.

Creating a Read-Write Property Initializer

Instead of the set contextual keyword, an alternative to create a property reader is with a contextual keyword named init. You primarily use it the same way you would proceed to create a set clause. Here is an example:

using static System.Console;

House residence = new();

WriteLine($"Market Value: {residence.MarketValue}");

public class House
{
    int price;

    public int MarketValue
    {
        get
        {
            return price;
        }

        init
        {
            price = value;
        }
    }
}

This time, to avoid the mistake of accessing a property that was not properly initialized, you must use a constructor (there are other means to initialize this type of property but we haven't studied them). To do this, create a constructor that uses a parameter that is the same type as the property. In the body of the constructor, initialize the property, which can be done by assigning it to the field that corresponds to the property. Then, when you create an object of the class, in the parentheses of the constructor, you must pass a value that initializes the property. Here is an example:

using static System.Console;

House residence = new House(450_000);

WriteLine($"Market Value: {residence.MarketValue}");

public class House
{
    int price;

    public int MarketValue
    {
        get
        {
            return price;
        }

        init
        {
            price = value;
        }
    }

    public House(int cost)
    {
        price = cost;
    }
}

An Automatic Property Initializer

We have already seen how to create an automatic read-write property with get and set clauses. Here is an example:

using static System.Console;

House residence = new();
residence.MarketValue = 450_000;

WriteLine($"Market Value: {residence.MarketValue}");

public class House
{
    public int MarketValue
    {
        get;
        set;
    }
}

Notice that you can initialize the property because it has a set accessor. In the same way, you can create an automatic property with get and init clauses. Here is an example:

public class House
{
    public int MarketValue
    {
        get;
        init;
    }
}

This time, if you want to initialize the property, you can (must) use a constructor that uses a parameter that you will assign to the property. Here is an example:

using static System.Console;

House residence = new House(450_000);

WriteLine($"Market Value: {residence.MarketValue}");

public class House
{
    public int MarketValue
    {
        get;
        init;
    }

    public House(int price)
    {
        MarketValue = price;
    }
}

The Default Constructor

Introduction

We know that we can create a class without adding a constructor to it. Here is an example:

class House
{
    string Location;
    string floorPlan;
    int Basement;
}

When you set up a class, if you don't add a constructor, the compiler creates one for you. Whether you create this constructor or the compiler creates it for you, the constructor with empty parentheses is called the default constructor. If you want, you can create your own default constructor. To explicitly create a default constructor, create a method that holds the same name as the class and leave the parentheses of that constructor empty. Here is an example:

class House
{
    public House()
    {
    }
}

If you are using Microsoft Visual Studio, to create a default constructor, right-click inside the class and click Insert Snippet... Double-click Visual C#. In the list that appears, double-click ctor:

Constructor

The Code Editor would use the name of the class to create the constructor.

When you create an object of the class (by declaring a variable of that class), whether you use that object or not, a constructor for the object is created. When an instance of a class has been declared, the default constructor is called, whether the object is used or not. This is illustrated in the following program:

using static System.Console;

BankAccount account = new BankAccount();

public class BankAccount
{
    public BankAccount()
    {
        WriteLine("New Bank Account");
    }
}

This would produce:

New Bank Account
Press any key to continue . . .

As you can see, even though the object was not used, just its creation was enough to call the default constructor. You may find it sometimes convenient to create your own constructor because, whether you create a default constructor or not, this does not negatively impact your program.

ApplicationPractical Learning: Using the Default Constructor

  1. To create a fefault constructor, change the class as follows:
    namespace Chemistry1.Models
    {
        public class Element
        {
            internal string Symbol       { get; set; }
            internal string ElementName  { get; set; }
            internal int    AtomicNumber { get; set; }
            internal double AtomicWeight { get; set; }
    
            public Element()
            {
            }
        }
    }

Initializing the Members of a Class

If a class has a default constructor, when an object is created from that class, that default constructor is automatically called. This feature makes the default constructor a good place to initialize the members of the class. You have many options.

When creating a class, you can declare a member variable and initialize it in the body of the class. Here is an example:

public class Element
{
    int AtomicNumber = 1;
}

Remember that a member created without the access level (public, private, or internal) is treated as private, and to re-inforce this, you can precede the member with the private keyword:

public class Element
{
    private int AtomicNumber = 1;
}

In the same way, you can declare and initialize as many members as you want in the body of the class. Here are examples:

public class Element
{
    string Symbol = "H";
    int AtomicNumber = 1;
}

As an alternative, you can create fields in the class, then create a constructor and initialize the field(s) in the constructor.

ApplicationPractical Learning: Creating a Constructor that Initializes

  1. To use a constructor to initialize some members of the class, change the constructor as follows:
    namespace Chemistry1
    {
        public class Element
        {
            internal string Symbol       { get; set; }
            internal string ElementName  { get; set; }
            internal int    AtomicNumber { get; set; }
            internal double AtomicWeight { get; set; }
    
            public Element()
            {
                AtomicNumber = 3;
                Symbol       = "Li";
                AtomicWeight = 6.94;
                ElementName  = "Lithium";
            }
        }
    }
  2. To execute the application to test it, on the main menu, click Debug -> Start Without Debugging
    Chemistry
    ------------------------
    Symbol:        Li
    Atomic Number: 3
    Element Name:  Lithium
    Atomic Weight: 6.94
    ========================
    
    Press any key to close this window . . .
  3. Press J to close the window and return to your programming environment

Creating an Object Using a Constructor

As we have seen in previous lessons, to create an object, declare a variable of a class. As we saw in previous and in this lessons, if the class doesn't have any constructor or it has a default constructor, initialize the object using the default constructor. When accessing each member from the object variable, you can use the period operator.

Initializing an Object

With or without a constructor, you can specify the values of an object at any time. This means that, even if a class has a default constructor and you have created its object, to set the values of the members of the class, access each member and assign the desired value.

ApplicationPractical Learning: Initializing an Object

  1. Click the PeriodicTable.cs tab
  2. To create and initialize an object, change the code as follows:
    using Chemistry1.Models;
    using static System.Console;
    
    Element be = new();
    
    be.Symbol       = "Be";
    be.AtomicNumber = 4;
    be.ElementName  = "Beryllium";
    be.AtomicWeight = 9.0121831;
    
    WriteLine("Chemistry");
    WriteLine("------------------------");
    WriteLine("Symbol:        " + be.Symbol);
    WriteLine($"Atomic Number: {be.AtomicNumber}");
    WriteLine("Element Name:  " + be.ElementName);
    WriteLine($"Atomic Weight: " + be.AtomicWeight);
    Write("========================");
  3. To execute the application to see the result, on the main menu, click Debug -> Start Without Debugging:
    Chemistry
    ------------------------
    Symbol:        Be
    Atomic Number: 4
    Element Name:  Beryllium
    Atomic Weight: 9.0121831
    ========================
    
    Press any key to close this window . . .
  4. To close the window and return to your programming environment, press N
  5. As an alternative, you can declare a variable and initialize it with the default constructor. Between the closing parenthesis and the semicolon, add the curly brackets that delimit a body in C#. In the curly brackets, add the name of a member of the class and initialize it with the value of your choice. Do the same for other desired members. You don't have to initialize each member and you don't have to list the members in the same order they appear in the class. The initializations must be separated by commas.
    For examples, change the code as follows:
    using Chemistry1.Models;
    using static System.Console;
    
    Element be = new();
    
    be.Symbol       = "Be";
    be.AtomicNumber = 4;
    be.ElementName  = "Beryllium";
    be.AtomicWeight = 9.0121831;
    
    Element b = new Element() { ElementName = "Boron", AtomicWeight = 10.81, AtomicNumber = 5, Symbol = "B" };
    
    WriteLine("Chemistry");
    WriteLine("------------------------");
    WriteLine("Symbol:        " + b.Symbol);
    WriteLine($"Atomic Number: {b.AtomicNumber}");
    WriteLine("Element Name:  " + b.ElementName);
    WriteLine($"Atomic Weight: " + b.AtomicWeight);
    Write("========================");
  6. To execute the application to see the result, on the main menu, click Debug -> Start Without Debugging
    Chemistry
    ------------------------
    Symbol:        B
    Atomic Number: 5
    Element Name:  Boron
    Atomic Weight: 10.81
    ========================
    
    Press any key to close this window . . .
  7. Close the window and return to your programming environment
  8. To make your code easier to read, you can put each curly bracket on its own line. You can also initialize each member on its own line.
    For an example, change the code as follows:
    usiing Chemistry1.Models;
    using static System.Console;
    
    Element be = new();
    
    be.Symbol       = "Be";
    be.AtomicNumber = 4;
    be.ElementName  = "Beryllium";
    be.AtomicWeight = 9.0121831;
    
    Element b = new() { ElementName = "Boron", AtomicWeight = 10.81, AtomicNumber = 5, Symbol = "B" };
    
    Element c = new Element()
    {
        Symbol = "C",
        AtomicNumber = 6,
        ElementName = "Carbon",
        AtomicWeight = 12.011
    };
    
    WriteLine("Chemistry");
    WriteLine("------------------------");
    WriteLine("Symbol:        " + c.Symbol);
    WriteLine($"Atomic Number: {c.AtomicNumber}");
    WriteLine("Element Name:  " + c.ElementName);
    WriteLine($"Atomic Weight: " + c.AtomicWeight);
    Write("========================");
  9. To execute the project, press Ctrl + F5:
    Chemistry
    ------------------------
    Symbol:        C
    Atomic Number: 6
    Element Name:  Carbon
    Atomic Weight: 12.011
    ========================
    
    Press any key to close this window . . .
  10. To close the window and return to your programming environment, press U
  11. Close your programming environment

Previous Copyright © 2001-2023, C# Key Saturday 29 April 2023 Next