Introduction to Classes and Objects

A Class Type as Parameter

An object of a class can be passed as argument. For example, a class type can be used as a parameter of a method of another class. When creating the method, simply provide the name of a class as type followed by a name for the parameter. You can use a class from the .NET library or your own class. As mentioned already, in the body of the method, you can ignore or use the parameter. When it comes to a class passed as parameter, its public and internal members are available to the method that uses it. When calling the method, you must provide an object created from the class.

ApplicationPractical Learning: Using a Property of a Class Type

  1. Start Microsoft Visual Studio and create a new Console App that supports the .NET 7.0 (Standard Term Support) named Chemistry3
  2. To create a new folder, in the Solution Explorer, right-click Chemistry3 -> Add -> New Folder
  3. Type Models as the name of the folder
  4. In the Solution Explorer, right-click Models -> Add -> Class...
  5. Change the file name to Element
  6. Click Add
  7. Change the document and class as follows:
    namespace Chemistry3.Models
    {
        public class Element
        {
            internal string ElementName  { get; set; }
            internal string Symbol       { get; set; }
            internal int    AtomicNumber { get; set; }
            internal double AtomicWeight { get; set; }
    
            public Element()                 { }
            public Element(string symbol) => Symbol = symbol;
            public Element(int number)    => AtomicNumber = number;
    
            public Element(int number, string symbol, string name, double mass)
            {
                Symbol       = symbol;
                ElementName  = name;
                AtomicWeight = mass;
                AtomicNumber = number;
            }
        }
    }
  8. In the Solution Explorer, right-click Program.cs and click Rename
  9. Type PeriodicTable (to get PeriodicTable.cs) and press enter
  10. Read the text in the message box and press Enter twice (to accept the name and access the document)
  11. Change the document as follows:
    using Chemistry3.Models;
    using static System.Console;
    
    Element h  = new(1, "H", "Hydrogen", 1.008);
    Element he = new(2, "He", "Helium", 4.002602);
    Element li = new(3, "Li", "Lithium", 6.94);
    Element be = new(4, "Be", "Beryllium", 9.0121831);
    Element b  = new(5, "B", "Boron", 10.81);
    Element c  = new(name: "Carbon", mass: 12.011, symbol: "C", number: 6);
    Element n  = new(7, "N", "Nitrogen", 14.007);
    Element o  = new(8, "O", "Oxygen", 15.999);
    
    Element f  = new Element(9);
    f.Symbol   = "F";
    f.AtomicWeight = 18.998;
    f.ElementName = "Fluorine";
    
    Element ne = new Element("Ne");
    ne.AtomicNumber = 10;
    ne.AtomicWeight = 20.180;
    ne.ElementName = "Neon";
    Element na = new(11, "Na", "Sodium", 22.990);
    
    PeriodicTable chem = new PeriodicTable();
  12. To create and call a function that takes an object as parameter, change the document as follows:
    using Chemistry3.Models;
    using static System.Console;
    
    void Present(Element obj)
    {
        WriteLine("Chemistry");
        WriteLine("------------------------");
        WriteLine("Symbol:        " + obj.Symbol);
        WriteLine($"Atomic Number: {obj.AtomicNumber}");
        WriteLine("Element Name:  " + obj.ElementName);
        WriteLine($"Atomic Weight: " + obj.AtomicWeight);
        Write("========================");
    }
    
    Element h  = new(1, "H", "Hydrogen", 1.008);
    Element he = new(2, "He", "Helium", 4.002602);
    Element li = new(3, "Li", "Lithium", 6.94);
    Element be = new(4, "Be", "Beryllium", 9.0121831);
    Element b  = new(5, "B", "Boron", 10.81);
    Element c  = new(name: "Carbon", mass: 12.011, symbol: "C", number: 6);
    Element n  = new(7, "N", "Nitrogen", 14.007);
    Element o  = new(8, "O", "Oxygen", 15.999);
    
    Element f  = new Element(9);
    f.Symbol   = "F";
    f.AtomicWeight = 18.998;
    f.ElementName = "Fluorine";
    
    Element ne = new Element("Ne");
    ne.AtomicNumber = 10;
    ne.AtomicWeight = 20.180;
    ne.ElementName = "Neon";
    Element na = new(11, "Na", "Sodium", 22.990);
    
    PeriodicTable chem = new PeriodicTable();
    
    chem.Present(na);
  13. To execute the application, on the main menu, click Debug -> Start Without Debugging
    Chemistry
    ------------------------
    Symbol:        Na
    Atomic Number: 11
    Element Name:  Sodium
    Atomic Weight: 22.99
    ========================
    
    Press any key to close this window . . .
  14. To close the window and return to your programming environment, press O

Returning an Object

A method can be made to produce an object. When creating the method, specify the name of the desired class before the name of the method. You can use your own class or use one of the many classes that come with the .NET library. In the body of the method, you can declare a variable of the class and initialize it. Before the closing bracket of the method, you must use the return keyword followed by the object and a semicolon. Here is an example:

public class Square
{
    private double s;

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

    public double CalculatePerimeter()
    {
        return s * 4;
    }

    public double CalculateArea()
    {
        return s * s;
    }
}

public class Plate
{
    private Square Create()
    {
        Square sqr = new Square(10);

		. . . Blah Blah Blah
            
        return sqr;
    }
}

Calling a Method that Returns an Object

To call a method that returns an object, you can first declare a variable of the class's return type and later assign the method call to it. Here is an example:

public class Square
{
    private double s;

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

public class Plate
{
    private Square Create()
    {
        Square sqr = new Square(10M);

	. . . Blah Blah Blah

        return sqr;
    }

    private void Describe()
    {
        Square s = new Square(0m);

	. . . Blah Blah Blah

        s = Create();
    }
}

Since the method internally initializes the object, you don't have to initialize the receiving variable. This means that you can directly assign the method call to it. Here is an example:

public class Square
{
    private double s;

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

    public double CalculatePerimeter()
    {
        return s * 4;
    }

    public double CalculateArea()
    {
        return s * s;
    }
}

public class Plate
{
    private Square Create()
    {
        Square sqr = new Square(10);

	return sqr;
    }

    private void Describe()
    {
	    Square s = Create();
    }
}

Practical LearningPractical Learning: Returning an Object

  1. To create and call a function that returns an object, change the document as follows:
    using Chemistry3.Models;
    using static System.Console;
    
    void Present(Element obj)
    {
        WriteLine("Chemistry");
        WriteLine("------------------------");
        WriteLine("Symbol:        " + obj.Symbol);
        WriteLine($"Atomic Number: {obj.AtomicNumber}");
        WriteLine("Element Name:  " + obj.ElementName);
        WriteLine($"Atomic Weight: " + obj.AtomicWeight);
        Write("========================");
    }
    
    Element Prepare()
    {
        Element h  = new(1, "H", "Hydrogen", 1.008);
        Element he = new(2, "He", "Helium", 4.002602);
        Element li = new(3, "Li", "Lithium", 6.94);
        Element be = new(4, "Be", "Beryllium", 9.0121831);
        Element b  = new(5, "B", "Boron", 10.81);
        Element c  = new(name: "Carbon", mass: 12.011, symbol: "C", number: 6);
        Element n  = new(7, "N", "Nitrogen", 14.007);
        Element o  = new(8, "O", "Oxygen", 15.999);
    
        Element f      = new Element(9);
        f.Symbol       = "F";
        f.AtomicWeight = 18.998;
        f.ElementName  = "Fluorine";
    
        Element ne = new Element("Ne");
        ne.AtomicNumber = 10;
        ne.AtomicWeight = 20.180;
        ne.ElementName = "Neon";
        Element na = new(11, "Na", "Sodium", 22.990);
        Element mg = new(12, "Mg", "Magnesium", 24.305);
    
        return mg;
    }
            
    PeriodicTable chem = new PeriodicTable();
    
    Element elm = chem.Prepare();
    
    chem.Present(elm);
  2. To execute the application, on the main menu, click Debug -> Start Without Debugging:
    Chemistry
    ------------------------
    Symbol:        Mg
    Atomic Number: 12
    Element Name:  Magnesium
    Atomic Weight: 24.305
    ========================
    
    Press any key to close this window . . .
  3. To close the window and return to your programming environment, press L

A Class Type as Reference

You can create a function or method that uses a parameter of a class type and the argument can be passed as reference. To do this, when creating the function or method, in its parentheses, precede the data type of the parameter with the ref keyword. When calling the function or method, precede the argument with the If you want to reinforce this, you can type the ref keyword. As seen with primitive types, if you pass a parameter by reference, if the function or method modifies the argument, this causes it to produce an object with a new version.

Practical LearningPractical Learning: Returning an Object

  1. Change the code as follows:
    using Chemistry3.Models;
    using static System.Console;
    
    void Prepare(ref Element e)
    {
        e.AtomicNumber = 13;
        e.Symbol = "Al";
        e.ElementName = "Aluminium";
        e.AtomicWeight = 26.982;
    }
    
    void Present(Element obj)
    {
        WriteLine("Chemistry");
        WriteLine("------------------------");
        WriteLine("Symbol:        " + obj.Symbol);
        WriteLine($"Atomic Number: {obj.AtomicNumber}");
        WriteLine("Element Name:  " + obj.ElementName);
        WriteLine($"Atomic Weight: " + obj.AtomicWeight);
        Write("========================");
    }
    
    Element elm = new();
    
    Prepare(ref elm);
    Present(elm);
  2. To execute, on the main menu, click Debug -> Start Without Debugging:Items:
    Chemistry
    ------------------------
    Symbol:        Al
    Atomic Number: 13
    Element Name:  Aluminium
    Atomic Weight: 26.982
    ========================
    Press any key to close this window . . .
  3. Start a new Console App that supports .NET 7.0 (Standard Term Support) and named ElectricityDistributionCompany1
  4. To create a new folder, in the Solution Explorer, right-click ElectricityDistributionCompany1 -> Add -> New Folder
  5. Type Models as the name of the folder
  6. In the Solution Edplorer, right-click Models -> Add -> Class...
  7. Change the file Name to BillPreparation
  8. Click Add
  9. Change the document or the class as follows:
    namespace ElectricityDistributionCompany1.Models
    {
        public class Meter
        {
            public string MeterNumber
            {
                get;
                set;
            }
    
            public string Make
            {
                get; set;
            }
            
            public string Model { get; set; }
    
            public string Describe()
            {
                return Make + " " + Model + " (Mtr #: " + MeterNumber + ")";
            }
        }
    }
  10. In the Solution Explorer, right-click Program.cs and click Rename
  11. Type BillProcessing (to get BillProcessing.cs) and press Enter
  12. Read the message box and click Yes
  13. Click the BusinessProcessing.cs tab to access its document
  14. Change the document as follows:
    using ElectricityDistributionCompany1;
    using static System.Console;
    
    Meter mtr = new Meter();
    
    WriteLine("=======================================================================");
    WriteLine("Electricity Distribution Company");
    WriteLine("=======================================================================");
    
    WriteLine("Enter the information about the water meter");
    Write("Meter #: ");
    mtr.MeterNumber = ReadLine();
    Write("Make:    ");
    mtr.Make = ReadLine();
    Write("Model:   ");
    mtr.Model = ReadLine();
    
    WriteLine("=======================================================================");
    WriteLine("Electricity Distribution Company");
    WriteLine("----------------------------------------------------------");
    
    WriteLine("Meter Details: " + mtr.Describe());
    Write("=======================================================================");
  15. To execute, on the main menu, click Debug -> Start Without Debugging:
  16. When requested, type the Meter # as FGL-6048 and press Enter
  17. For the Make, type Thiesen Power and press Enter
  18. For the Model, type KV-2604 and press Enter:
    =======================================================================
    Electricity Distribution Company
    =======================================================================
    Enter the information about the water meter
    Meter #: FGL-6048
    Make:    Thiesen Power
    Model:   KV-2604
    =======================================================================
    Electricity Distribution Company
    ----------------------------------------------------------
    Meter Details: Thiesen Power KV-2604 (Mtr #: FGL-6048)
    =======================================================================
    
    Press any key to close this window . . .
  19. To close the window and return to Microsoft Visual Studio, press Enter

Returning an Object From a Class's Own Method

You can create a method that returns an instance of its own class. To start, on the left side of the method, enter the name of the class. Here is an example:

public class Employee
{
    public Employee Create()
    {
    }
}

There are various ways you can deal with the method. If you want to return a new value of the class, you can declare an instance of the class, initialize it, and then return it. Here is an example:

public class Employee
{
    public int emplNbr;
    public string fName;
    public string lName;
    public double salary;

    public Employee Create()
    {
	Employee staff = new Employee();

        staff.emplNbr = 947059;
	    staff.fName = "Paull";
       	staff.lName = "Motto";
        staff.salary = 54925;

        return staff;
    }
}

Another technique consists of declaring an instance of the class and initialize its fields with those of the class. Here is an example:

public class Employee
{
    public int emplNbr;
    public string fName;
    public string lName;
    public double salary;

    public Employee Create()
    {
       	Employee staff = new Employee();

        staff.emplNbr = emplNbr;
	staff.fName = fName;
        staff.lName = lName;
	staff.salary = salary;

       	return staff;
    }
}

Most of the time, this technique may not be very useful. As an alternative, you can pass some parameters to the method and then initialize the fields of the class with those parameters. After doing this, when calling the method, you can assign it to an object of the same class.

Practical LearningPractical Learning: Returning an Object From a Class's Own Method

Using the Returned Object of a Method

Notice that this new CounterReading class contains a method that returns an object of the type of the other class. You can call such a method to get a reference to the other class. That reference, used as an object, can be used as a valid object gotten from the first class.

Practical LearningPractical Learning: Using the Returned Object of a Method

  1. For an example of doing this, click the BillProcessing.cs tab and change the document as follows:
    using ElectricityDistributionCompany1.Models;
    using static System.Console;
    
    CounterReading cr = new CounterReading();
    
    Meter mtr = cr.Read();
    
    WriteLine("=======================================================================");
    WriteLine("Electricity Distribution Company");
    WriteLine("=======================================================================");
    
    WriteLine("Enter the information about the water meter");
    Write("Meter #: ");
    mtr.MeterNumber = ReadLine();
    Write("Make:    ");
    mtr.Make = ReadLine();
    Write("Model:   ");
    mtr.Model = ReadLine();
    
    WriteLine("=======================================================================");
    WriteLine("Electricity Distribution Company");
    WriteLine("----------------------------------------------------------");
    
    WriteLine("Meter Details: " + mtr.Describe());
    Write("=======================================================================");
  2. To execute, on the main menu, click Debug -> Start Without Debugging
  3. For the Meter #, type WEJ-9284 and press Enter
  4. For the Make, type Pepperus Worldwide and press Enter
  5. For the Model, type i2024 and press Enter:
    =======================================================================
    Electricity Distribution Company
    =======================================================================
    Enter the information about the water meter
    Meter #: WEJ-9284
    Make:    Pepperus Worlwide
    Model:   i2024
    =======================================================================
    Electricity Distribution Company
    ----------------------------------------------------------
    Meter Details: Pepperus Worlwide i2024 (Mtr #: WEJ-9284)
    =======================================================================
    
    Press any key to close this window . . .
  6. To close the window and return to Microsoft Visual Studio, press Enter
  7. To consider one more class, in the BillPreparation.cs document, add a new class named Calculations as follows:
    namespace ElectricityDistributionCompany1.Models
    {
        public class Meter
        {
            public string MeterNumber
            {
                get;
                set;
            }
    
            public string Make
            {
                get; set;
            }
    
            public string Model { get; set; }
    
            public string Describe()
            {
                return Make + " " + Model + " (Mtr #: " + MeterNumber + ")";
            }
        }
    
        public class CounterReading
        {
            private Meter mtr;
            public int TotalUse { get; set; }
    
            public CounterReading()
            {
                mtr = new Meter();
            }
    
            public Meter Read()
            {
                return mtr;
            }
        }
    
        public class Calculations
        {
            public CounterReading Useage { get; set; }
    
            public Calculations()
            {
                Useage = new CounterReading();
            }
    
            public CounterReading Prepare()
            {
                return Useage;
            }
        }
    }
  8. Click the BillProcessing.cs tab and change the document as follows:
    using ElectricityDistributionCompany1;
    using static System.Console;
    
    Calculations cals = new Calculations();
    CounterReading cr = cals.Prepare();
    
    Meter mtr = cr.Read();
    
    WriteLine("=======================================================================");
    WriteLine("Electricity Distribution Company");
    WriteLine("=======================================================================");
    
    WriteLine("Enter the information about the water meter");
    Write("Meter #: ");
    mtr.MeterNumber = ReadLine();
    Write("Make:    ");
    mtr.Make = ReadLine();
    Write("Model:   ");
    mtr.Model = ReadLine();
    
    WriteLine("=======================================================================");
    WriteLine("Electricity Distribution Company");
    WriteLine("----------------------------------------------------------");
    
    WriteLine("Meter Details: " + mtr.Describe());
    Write("=======================================================================");
  9. To execute, on the main menu, click Debug -> Start Without Debugging
  10. For the Meter #, type KBV-9728 and press Enter
  11. For the Make, type Frellatta International and press Enter
  12. For the Model, type G2806T and press Enter:
    =======================================================================
    Electricity Distribution Company
    =======================================================================
    Enter the information about the water meter
    Meter #: KBV-9728
    Make:    Frellatta International
    Model:   G2806T
    =======================================================================
    Electricity Distribution Company
    -----------------------------------------------------------------------
    Meter Details: Frellatta International G2806T (Mtr #: KBV-9728)
    =======================================================================
    
    Press any key to close this window . . .
  13. To close the window and return to Microsoft Visual Studio, press Enter
  14. Once again, the new class contains a method that returns an object of a class type. We saw that, to use the return object of a method, you can first declare a variable and then assign the method call to it. That type of variable may be necessary only if you are planning to call the method more than once.

    When you call a method that returns an object, the call holds an actual value of the class. As a result, you can call the method directly where the object is needed. If the class of that object contains a method that returns an object you need, you can call that other method directly after the parentheses of the previously mentioned method. For many examples, click the BillPreparation.cs tab

  15. Change the existing classes and add a new class as follows:
    namespace ElectricityDistributionCompany1.Models
    {
        public class Meter
        {
            public string MeterNumber
            {
                get;
                set;
            }
    
            public string Make
            {
                get; set;
            }
    
            public string Model { get; set; }
    
            public string Describe()
            {
                return Make + " " + Model + " (Mtr #: " + MeterNumber + ")";
            }
        }
    
        public class CounterReading
        {
            private Meter mtr;
            public int TotalUse { get; set; }
    
            public CounterReading()
            {
                mtr = new();
    
                mtr.Make = "Horriander";
                mtr.Model = "CXL 3600";
                mtr.MeterNumber = "M927084";
            }
    
            public Meter Read() => mtr;
        }
    
        public class Calculations
        {
            public CounterReading Useage { get; set; } = new CounterReading();
    
            public const double CustomerCharge = 7.60;
            public const double DeliveryTaxRate = 6.20;
            public const double EnergyChargeRate = 6.2655;
            public const double GridResilienceChargeRate = 12;
            public const double EnvironmentSurchargeRate = 14.90;
    
            public Calculations()
            {
                Useage.TotalUse = 1497;
            }
    
            public double CalculateEnergyCharges()
            {
                return Useage.TotalUse * EnergyChargeRate / 100;
            }
    
            public double CalculateGridResilienceCharges()
            {
                return Useage.TotalUse * GridResilienceChargeRate / 100000;
            }
    
            public double CalculateDeliveryTaxes()
            {
                return Useage.TotalUse * DeliveryTaxRate / 10000;
            }
    
            public double CalculateEnvironmentalSurcharge()
            {
                return Useage.TotalUse * EnvironmentSurchargeRate / 100000;
            }
    
            public double EvaluateAmountDue()
            {
                return CustomerCharge +
                       CalculateEnergyCharges() +
                       CalculateGridResilienceCharges() +
                       CalculateDeliveryTaxes() +
                       CalculateEnvironmentalSurcharge();
            }
    
            public CounterReading Prepare()
            {
                return Useage;
            }
        }
    
        public class ElectriBill
        {
            private Calculations values;
    
            public ElectriBill()
            {
                values = new Calculations();
            }
    
            public Calculations Prepare()
            {
                return values;
            }
        }
    }
  16. For examples of calling objects's methods directly where they are needed, click the BillProcessing.cs tab and change the document as follows:
    using ElectricityDistributionCompany1.Models;
    using static System.Console;
    
    ElectriBill eb = new();
    
    WriteLine("===================================================================");
    WriteLine("Electricity Distribution Company");
    WriteLine("===================================================================");
    
    WriteLine("Meter #:                     {0}", eb.Prepare().Useage.Read().MeterNumber);
    WriteLine("Make:                        {0}", eb.Prepare().Useage.Read().Make);
    WriteLine("Model:                       {0}", eb.Prepare().Useage.Read().Model);
    WriteLine($"Meter Details:               {eb.Prepare().Prepare().Read().Describe()}");
    WriteLine("-------------------------------------------------------------------");
    WriteLine($"Customer Charge:             {Calculations.CustomerCharge:F}");
    WriteLine($"Delivery Tax Rate:           {Calculations.DeliveryTaxRate:F}");
    WriteLine($"Energy Charge Rate:          {Calculations.EnergyChargeRate:F}");
    WriteLine($"Grid Resilience Charge Rate: {Calculations.GridResilienceChargeRate:F}");
    WriteLine($"Environment Surcharge Rate:  {Calculations.EnvironmentSurchargeRate:F}");
    WriteLine("-------------------------------------------------------------------");
    WriteLine($"Total Use:                   {eb.Prepare().Useage.TotalUse:f}");
    WriteLine($"Environmental Surcharge:     {eb.Prepare().CalculateEnvironmentalSurcharge():f}");
    WriteLine($"Delivery Taxes:              {eb.Prepare().CalculateDeliveryTaxes():f}");
    WriteLine($"Grid Resilience Charges.:    {eb.Prepare().CalculateGridResilienceCharges():f}");
    WriteLine($"Energy Charges.:             {eb.Prepare().CalculateEnergyCharges():f}");
    WriteLine($"Amount Due.:                 {eb.Prepare().EvaluateAmountDue():f}");
    Write("=======================================================================");
  17. To execute, press Ctrl + F5
    ===================================================================
    Electricity Distribution Company
    ===================================================================
    Meter #:                     M927084
    Make:                        Horriander
    Model:                       CXL 3600
    Meter Details:               Horriander CXL 3600 (Mtr #: M927084)
    -------------------------------------------------------------------
    Customer Charge:             7.60
    Delivery Tax Rate:           6.20
    Energy Charge Rate:          6.27
    Grid Resilience Charge Rate: 12.00
    Environment Surcharge Rate:  14.90
    -------------------------------------------------------------------
    Total Use:                   1497.00
    Environmental Surcharge:     0.22
    Delivery Taxes:              0.93
    Grid Resilience Charges.:    0.18
    Energy Charges.:             93.79
    Amount Due.:                 102.73
    ===================================================================
    
    Press any key to close this window . . .
  18. To close the window and return to your programming environment, press 1
  19. Of course, you can apply the same technique if the code is written inside the method of a class. For an example, click the BillPreparation.cs tab and add a method to the ElectricBill class as follows (the other changes are only made to reduce the number of lines of code):
    namespace ElectricityDistributionCompany1.Models
    {
        public class Meter
        {
            public string MeterNumber   { get; set; }
            public string Make          { get; set; }
            public string Model         { get; set; }
    
            public string Describe() => Make + " " + Model + " (Mtr #: " + MeterNumber + ")";
        }
    
        public class CounterReading
        {
            private Meter mtr;
            public int TotalUse { get; set; }
    
            public CounterReading()
            {
                mtr             = new();
                mtr.Make        = "Horriander";
                mtr.Model       = "CXL 3600";
                mtr.MeterNumber = "M927084";
            }
    
            public Meter Read() => mtr;
        }
    
        public class Calculations
        {
            public CounterReading Useage { get; set; } = new CounterReading();
    
            public const double CustomerCharge           = 7.60;
            public const double DeliveryTaxRate          = 6.20;
            public const double EnergyChargeRate         = 6.2655;
            public const double GridResilienceChargeRate = 12;
            public const double EnvironmentSurchargeRate = 14.90;
    
            public        Calculations()                    => Useage.TotalUse = 1497;
    
            public double CalculateEnergyCharges()          => Useage.TotalUse * EnergyChargeRate / 100;
            public double CalculateGridResilienceCharges()  => Useage.TotalUse * GridResilienceChargeRate / 100000;
            public double CalculateDeliveryTaxes()          => Useage.TotalUse * DeliveryTaxRate / 10000;
            public double CalculateEnvironmentalSurcharge() => Useage.TotalUse * EnvironmentSurchargeRate / 100000;
    
            public double EvaluateAmountDue()
            {
                return CustomerCharge +
                       CalculateEnergyCharges() +
                       CalculateGridResilienceCharges() +
                       CalculateDeliveryTaxes() +
                       CalculateEnvironmentalSurcharge();
            }
    
            public CounterReading Prepare() => Useage;
        }
    
        public class ElectriBill
        {
            private Calculations values;
    
            public ElectriBill()
            {
                values = new();
            }
    
            public Calculations Prepare()
            {
                return values;
            }
    
            public string Summarize()
            {
                string strSummary = values.Prepare().Read().Describe();
    
                return strSummary;
            }
        }
    }
  20. Click the BillProcessing.cs tab and change the class as follows:
    using ElectricityDistributionCompany1;
    using static System.Console;
    
    var eb = new ElectriBill();
    
    WriteLine("===================================================================");
    WriteLine("Electricity Distribution Company");
    WriteLine("===================================================================");
    
    WriteLine("Meter #:                     {0}", eb.Prepare().Useage.Read().MeterNumber);
    WriteLine("Make:                        {0}", eb.Prepare().Useage.Read().Make);
    WriteLine("Model:                       {0}", eb.Prepare().Useage.Read().Model);
    WriteLine($"Meter Details:               {eb.Summarize()}");
    WriteLine("-------------------------------------------------------------------");
    WriteLine($"Customer Charge:             {Calculations.CustomerCharge:F}");
    WriteLine($"Delivery Tax Rate:           {Calculations.DeliveryTaxRate:F}");
    WriteLine($"Energy Charge Rate:          {Calculations.EnergyChargeRate:F}");
    WriteLine($"Grid Resilience Charge Rate: {Calculations.GridResilienceChargeRate:F}");
    WriteLine($"Environment Surcharge Rate:  {Calculations.EnvironmentSurchargeRate:F}");
    WriteLine("-------------------------------------------------------------------");
    WriteLine($"Total Use:                   {eb.Prepare().Useage.TotalUse:f}");
    WriteLine($"Environmental Surcharge:     {eb.Prepare().CalculateEnvironmentalSurcharge():f}");
    WriteLine($"Delivery Taxes:              {eb.Prepare().CalculateDeliveryTaxes():f}");
    WriteLine($"Grid Resilience Charges.:    {eb.Prepare().CalculateGridResilienceCharges():f}");
    WriteLine($"Energy Charges.:             {eb.Prepare().CalculateEnergyCharges():f}");
    WriteLine($"Amount Due.:                 {eb.Prepare().EvaluateAmountDue():f}");
    Write("=======================================================================");
  21. To execute, on the main menu, click Debug -> Start Without Debugging
  22. Press Enter to close the window and return to your programming environment
  23. To make your code easier to read, you can put each call on its own line. For an example, click the BillPreparation.cs tab change the last method of the ElectricBill class as follows:
    namespace ElectricityDistributionCompany1.Models
    {
        public class Meter
        {
            . . .
        }
    
        public class CounterReading
        {
            . . .
        }
    
        public class Calculations
        {
            . . .
        }
    
        public class ElectriBill
        {
            private Calculations values;
    
            public ElectriBill()
            {
                values = new();
            }
    
            public Calculations Prepare() => values;
    
            public string Summarize()
            {
                string strSummary = values.Prepare()
                                          .Read()
                                          .Describe();
    
                return strSummary;
            }
        }
    }
  24. Click the BillProcessing.cs tab and change its class as follows:
    using ElectricityDistributionCompany1.Models;
    using static System.Console;
    
    var eb = new ElectriBill();
    
    WriteLine("===================================================================");
    WriteLine("Electricity Distribution Company");
    WriteLine("===================================================================");
    
    WriteLine("Meter #:                     {0}", eb.Prepare()
                                                    .Useage
                                                    .Read()
                                                    .MeterNumber);
    WriteLine("Make:                        {0}", eb.Prepare()
                                                    .Useage
                                                    .Read().Make);
    WriteLine("Model:                       {0}", eb.Prepare()
                                                    .Useage
                                                    .Read().Model);
    WriteLine($"Meter Details:               {eb.Summarize()}");
    WriteLine("-------------------------------------------------------------------");
    WriteLine($"Customer Charge:             {Calculations.CustomerCharge:F}");
    WriteLine($"Delivery Tax Rate:           {Calculations.DeliveryTaxRate:F}");
    WriteLine($"Energy Charge Rate:          {Calculations.EnergyChargeRate:F}");
    WriteLine($"Grid Resilience Charge Rate: {Calculations.GridResilienceChargeRate:F}");
    WriteLine($"Environment Surcharge Rate:  {Calculations.EnvironmentSurchargeRate:F}");
    WriteLine("-------------------------------------------------------------------");
    WriteLine($"Total Use:                   {eb.Prepare().Useage.TotalUse:f}");
    WriteLine($"Environmental Surcharge:     {eb.Prepare().CalculateEnvironmentalSurcharge():f}");
    WriteLine($"Delivery Taxes:              {eb.Prepare().CalculateDeliveryTaxes():f}");
    WriteLine($"Grid Resilience Charges.:    {eb.Prepare().CalculateGridResilienceCharges():f}");
    WriteLine($"Energy Charges.:             {eb.Prepare().CalculateEnergyCharges():f}");
    WriteLine($"Amount Due.:                 {eb.Prepare().EvaluateAmountDue():f}");
    Write("=======================================================================");
  25. To execute, on the main menu, click Debug -> Start Without Debugging
  26. Press Enter to close the window and return to your programming environment

A Read-Only Object Type

We already know that if we create a field that is a class type, we must find a way to initialize the field before it. Such an intialization can be done in a constructor. When studying fields created from primitive types, we saw that, to indicate that the field is initialized in a constructor of the class where the field if created, you can mark that field with as readonly.

ApplicationPractical Learning: Creating a Read-Only Object

  1. To create read-only fields, click the BillPreparation.cs tab and make the following changes:
    namespace ElectricityDistributionCompany1.Models
    {
        public class Meter
        {
            public string MeterNumber   { get; set; }
            public string Make          { get; set; }
            public string Model         { get; set; }
    
            public string Describe() => Make + " " + Model + " (Mtr #: " + MeterNumber + ")";
        }
    
        public class CounterReading
        {
            private readonly Meter mtr;
            public int TotalUse { get; set; }
    
            public CounterReading()
            {
                mtr             = new();
                mtr.Make        = "Horriander";
                mtr.Model       = "CXL 3600";
                mtr.MeterNumber = "M927084";
            }
    
            public Meter Read() => mtr;
        }
    
        public class Calculations
        {
            public CounterReading Useage { get; set; } = new CounterReading();
    
            public const double CustomerCharge           = 7.60;
            public const double DeliveryTaxRate          = 6.20;
            public const double EnergyChargeRate         = 6.2655;
            public const double GridResilienceChargeRate = 12;
            public const double EnvironmentSurchargeRate = 14.90;
    
            public        Calculations()                    => Useage.TotalUse = 1497;
    
            public double CalculateEnergyCharges()          => Useage.TotalUse * EnergyChargeRate / 100;
            public double CalculateGridResilienceCharges()  => Useage.TotalUse * GridResilienceChargeRate / 100000;
            public double CalculateDeliveryTaxes()          => Useage.TotalUse * DeliveryTaxRate / 10000;
            public double CalculateEnvironmentalSurcharge() => Useage.TotalUse * EnvironmentSurchargeRate / 100000;
    
            public double EvaluateAmountDue()
            {
                return CustomerCharge +
                       CalculateEnergyCharges() +
                       CalculateGridResilienceCharges() +
                       CalculateDeliveryTaxes() +
                       CalculateEnvironmentalSurcharge();
            }
    
            public CounterReading Prepare() => Useage;
        }
    
        public class ElectriBill
        {
            private readonly Calculations values;
    
            public ElectriBill()
            {
                values = new();
            }
    
            public Calculations Prepare() => values;
    
            public string Summarize()
            {
                return values.Prepare()
                             .Read()
                             .Describe();
            }
        }
    }
  2. To execute the program, press Ctrl + F5
  3. Close the window and return to your programming environment

Passing a Class in, and Returning an Object from, its Own Method

In a class, you can create a method that both uses a parameter that is of the type of its own class and returns an object that is the type of its own class. Here is an example:

public class Circle
{
    public Circle Create(Circle cir)
    {
    }
}

As mentioned already, in the body of the method, the parameter has access to all members of the class. Before exiting the method, make sure you return an object that is the type of the class. Here is an example:

public clas
Circle
{
    public Circle Create(Circle cir)
    {
       	Circle rounder = new Circle();

        return rounder;
    }
}

Involving a Class in its Own Members

The Type of a Field as its Own Class

In a class, you can create a field that is the type of its own class. Here is an example:

public class Employee
{
    public int EmplNbr;
    public string FName;
    public string LName;
    public double Salary;

    Employee staff;
}

Before using the field, you must initialize it. You have many options. You can initialize the field directly in the body of the class. Here are examples:

namespace Chemistry
{
    public class Element
    {
        internal string ElementName  { get; set; }
        internal string Symbol       { get; set; }
        internal int    AtomicNumber { get; set; }
        internal double AtomicWeight { get; set; }

        public Element(int number, string symbol, string name, double mass)
        {
            Symbol       = symbol;
            ElementName  = name;
            AtomicWeight = mass;
            AtomicNumber = number;
        }

        Element Si = new Element(14, "Si", "Silicon", 28.085);
        Element P = new Element(number: 15, symbol: "P", name: "Phosphorus", mass: 30.974);
        Element S = new(16, "S", "Sulfur", 32.06);
        Element Cl = new(number: 17, symbol: "Cl", name: "Chlorine", mass: 35.45);
        Element Ar = new(name: "Argon", number: 18, symbol: "Ar", mass: 39.948);
        Element K = new Element()
        {
            AtomicNumber = 19,
            Symbol = "K",
            AtomicWeight = 39.098,
            ElementName = "Potassium"
        };
    }
}

If you do this, the field can be accessed by any member of the same class. If you make the field public or internal, if you decide to use it outside the class, you can access the public and internal members of the class through that field.

Passing a Class Type to its Own Method

An instance of a class can be passed as an argument to one of its own methods. To do this, you primarily pass the argument as if it were any type. Here is an example:

public class HotelRoom
{
    public void Display(HotelRoom room)
    {
    }
}

In the body of the method, you can do whatever you want. You can, or you may not, use the parameter. Still, if you decide to use the parameter, know that all the other members of the class are accessible through the parameter. One of the simplest ways you can use the parameter is to assign each of its values to the equivalent member of the class. Here is an example:

public class HotelRoom
{   
    private string roomNbr;
    private int    capacity;
    private string roomType;
    private double rate;

    public void Display(HotelRoom room)
    {
       	roomNbr = room.roomNbr;
	capacity = room.capacity;
    	roomType = room.roomType;
        rate = room.rate;
    }
}

When calling the method, make sure you pass an instance of the class to it. You can first create and define an object of the class, then pass it.

A Class Type as a Parameter to its Own Constructor

Just like a class can be used as the type of a parameter in one of its own methods, a class type can be used as a parameter to one of its own constructors. This can be done as follows:

public class HotelRoom
{
    public HotelRoom(HotelRoom sample)
    {
    }
}

Instead of a formal method, you can use a constructor of the class to pass an instance of the same class. Then, in the constructor, use the argument as you see fit, knowing that all the members of the class are available.

Returning an Object From a Class's Own Method

You can create a method that returns an instance of its own class. To start, on the left side of the method, enter the name of the class. Here is an example:

public class Employee
{
    public Employee Create()
    {
    }
}

There are various ways you can deal with the method. If you want to return a new value of the class, you can declare an instance of the class, initialize it, and then return it. Here is an example:

public class Employee
{
    int emplNbr;
    string fName;
    string lName;
    double salary;

    public Employee Create()
    {
        Employee staff = new Employee();

        staff.emplNbr = 947059;
        staff.fName = "Paull";
        staff.lName = "Motto";
        staff.salary = 54925;

        return staff;
    }
}

Another technique consists of declaring an instance of the class and initialize its fields with those of the class. Here is an example:

public class Employee
{
    int emplNbr;
    string fName;
    string lName;
    double salary;

    public Employee Create()
    {
        Employee staff = new Employee();

        staff.emplNbr = emplNbr;
        staff.fName = fName;
        staff.lName = lName;
        staff.salary = salary;

        return staff;
    }
}

Most of the time, this technique may not be very useful. As an alternative, you can pass some parameters to the method and then initialize the fields of the class with those parameters. After doing this, when calling the method, you can assign it to an object of the same class.

ApplicationPractical Learning: Ending the Lesson


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