The Nullity and Type of Objects

Checking the Type of an Object

We have already been introduced to a data type named object. This is the most fundamental type in C# (and the .NET Framework) and, in some cases, it can be used in place of any data type. As a matter of fact, if you are creating a function that would treat various types of objects, you can pass an object type to it. Then, in the body of the function, before doing anything, find out what type was passed as argument. To do that, use the is operator to compare the argument to the desired type. Here is an example:

using static System.Console;

void Present(object obj)
{
    if (obj is Microwave)
    {
        Microwave mw = (Microwave)obj;

        WriteLine("Make and Model:    " + mw.Make + " " + mw.Model);
        WriteLine("Capacity:          {0}", mw.Capacity);
        WriteLine("Microwave Options: {0}", mw.MenuOptions);
        WriteLine("==========================================");
    }
}

Microwave machine = null;

Present(machine);

machine = new Microwave()
{
    Make        = "Farberware",
    Model       = "FMO12AHTBSG",
    Capacity    = 1.2,
    MenuOptions = 9
};

Person friend = new Person();
Present(friend);

Present(machine);

Bicycle voyage = new Bicycle();
Present(voyage);

public class Microwave
{
    public string Make { get; set; }
    public string Model { get; set; }
    public double Capacity { get; set; }
    public int MenuOptions { get; set; }
}

public class Person
{
    public string Name { get; set; }
}

public class Bicycle
{
    public int    Speeds { get; set; }
    public double Price  { get; set; }
}

Practical LearningPractical Learning: Introducing Nullity of Objects

  1. Start Microsoft Visual Studio.
    Create a C# Console App that supports the .NET 8.0 (Long-Term Support).
    Name the project as StellarWaterPoint5
  2. Change the Program.cs document as follows:
    using static System.Console;
    
    (Classification iClass, string name) IdentifyAccount(string aType)
    {
        if (aType == "1")
            return (Classification.Residential, "Residential Household");
        else if (aType == "2")
            return (Classification.NonProfit, "Social/Non-Profit Organization");
        else if (aType == "3")
            return (Classification.WaterIntensive, "Water Intensive Business (Laudromat, Hair Salon, etc)");
        else if (aType == "4")
            return (Classification.GeneralUse, "General Business, Government");
        else
            return (Classification.Other, "Other");
    }
    
    double Subtract(in double a, in double b)
    {
        return a - b;
    }
    
    double CalculateHCFTotal(double gallons)
    {
        return gallons / 748.00;
    }
    
    (double a, double b, double c) EvaluateTherms(in double hcf)
    {
        double first;
        double next;
        double above;
    
        if (hcf is > 40.00)
        {
            first = 25.00 * 1.5573;
            next = 15.00 * 1.2264;
            above = (hcf - 40.00) * 0.9624;
        }
        else if (hcf > 25.00)
        {
            first = 25.00 * 1.5573;
            next = (hcf - 25.00) * 1.2264;
            above = 0.00;
        }
        else
        {
            first = hcf * 1.5573;
            next = 0.00;
            above = 0.00;
        }
    
        return (first, next, above);
    }
    
    double EvaluateSewerCharges(in double charges, in Classification @class)
    {
        double result;
    
        switch (@class)
        {
            case Classification.Residential:
                result = charges * 0.2528;
                break;
            case Classification.NonProfit:
                result = charges * 0.0915;
                break;
            case Classification.WaterIntensive:
                result = charges * 1.5865;
                break;
            case Classification.GeneralUse:
                result = charges * 0.6405;
                break;
            default:
                result = charges * 1.2125;
                break;
        }
    
        return result;
    }
    
    double EvaluateEnvironmentCharges(in double charges, in Classification @class)
    {
        double result;
    
        switch (@class)
        {
            case Classification.Residential:
                result = charges * 0.0025;
                break;
            case Classification.NonProfit:
                result = charges * 0.0015;
                break;
            case Classification.WaterIntensive:
                result = charges * 0.0105;
                break;
            case Classification.GeneralUse:
                result = charges * 0.0045;
                break;
            default:
                result = charges * 0.0125;
                break;
        }
    
        return result;
    }
    
    double EvaluateServiceCharges(in double charges, in Classification @class)
    {
        double result;
    
        switch (@class)
        {
            case Classification.Residential:
                result = charges * 0.0328;
                break;
            case Classification.NonProfit:
                result = charges * 0.0115;
                break;
            case Classification.WaterIntensive:
                result = charges * 0.1015;
                break;
            case Classification.GeneralUse:
                result = charges * 0.0808;
                break;
            default:
                result = charges * 0.1164;
                break;
        }
    
        return result;
    }
    
    double AddTriple(in (double a, double b, double c) triple)
    {
        return triple.a + triple.b + triple.c;
    }
    
    double Add3(in double a, in double b, in double c)
    {
        return a + b + c;
    }
    
    double Add4(in double a, in double b, in double c, in double d)
    {
        return a + b + c + d;
    }
    
    double CalculateLocalTaxes(in double charges, in Classification @class)
    {
        double result;
    
        switch (@class)
        {
            case Classification.Residential:
                result = charges * 0.115;
                break;
            case Classification.NonProfit:
                result = charges * 0.085;
                break;
            case Classification.WaterIntensive:
                result = charges * 0.825;
                break;
            case Classification.GeneralUse:
                result = charges * 0.315;
                break;
            default:
                result = charges * 0.625;
                break;
        }
    
        return result;
    }
    
    double CalculateStateTaxes(in double charges, in Classification @class)
    {
        double result;
    
        switch (@class)
        {
            case Classification.Residential:
                result = charges * 0.035;
                break;
            case Classification.NonProfit:
                result = charges * 0.015;
                break;
            case Classification.WaterIntensive:
                result = charges * 0.105;
                break;
            case Classification.GeneralUse:
                result = charges * 0.065;
                break;
            default:
                result = charges * 0.815;
                break;
        }
    
        return result;
    }
    
    string GetCustomerType()
    {
        WriteLine("Stellar Water Point");
        WriteLine("===========================================================");
        WriteLine("To prepare an invoice, enter the following information");
        WriteLine("Types of Accounts");
        WriteLine("1. Residential Household");
        WriteLine("2. Social/Non-Profit Organization");
        WriteLine("3. Water Intensive Business (Laudromat, etc)");
        WriteLine("4. General Business");
        WriteLine("0. Other");
        Write("Enter Type of Account:         ");
        string answer = ReadLine()!;
        WriteLine("-----------------------------------------------------------");
    
        return answer;
    }
    
    int ReadCounter(out int start, out int end)
    {
        end   = 0;
        start = 0;
    
        try
        {
            Write("Counter Reading Start:         ");
            start = int.Parse(ReadLine()!);
        }
        catch(Exception ex) when (ex is FormatException fex)
        {
            WriteLine("The counter reading start value you entered is not valid.");
            WriteLine("The error produced is: " + fex.Message);
        }
    
        try
        {
            Write("Counter Reading End:           ");
            end = int.Parse(ReadLine()!);
        }
        catch (Exception ex) when (ex is FormatException fex)
        {
            WriteLine("The counter reading end value you entered is not valid.");
            WriteLine("The error produced is: " + fex.Message);
        }
    
        return 1_000;
    }
    
    int    readingEnd;
    int    readingStart;
    string acntType = GetCustomerType();
    
    _ = ReadCounter(out readingStart, out readingEnd);
    
    var account = IdentifyAccount(acntType);
    double gallons = Subtract(readingEnd, readingStart);
    double HCFValue = CalculateHCFTotal(gallons);
    (double First25Therms, double Next15Therms, double Above40Therms) therms = EvaluateTherms(HCFValue);
    double water = AddTriple(therms);
    double sewer = EvaluateSewerCharges(water, account.iClass);
    double environmentCharges = EvaluateEnvironmentCharges(water, account.iClass);
    double serviceCharges = EvaluateServiceCharges(water, account.iClass);
    double totalCharges = Add4(water, sewer, environmentCharges, serviceCharges);
    double localTaxes = CalculateLocalTaxes(totalCharges, account.iClass);
    double stateTaxes = CalculateStateTaxes(totalCharges, account.iClass);
    double amountDue = Add3(totalCharges, localTaxes, stateTaxes);
    
    WriteLine("===========================================================");
    WriteLine("Stellar Water Point - Customer Invoice");
    WriteLine("Account Type:               {0}", account.name);
    WriteLine("===========================================================");
    WriteLine("Meter Reading");
    WriteLine("-----------------------------------------------------------");
    WriteLine("Counter Reading Start:      {0,10}", readingStart);
    WriteLine("Counter Reading End:        {0,10}", readingEnd);
    WriteLine("Total Gallons Consumed:     {0,10}", gallons);
    WriteLine("===========================================================");
    WriteLine("Therms Evaluation");
    WriteLine("-----------------------------------------------------------");
    WriteLine("HCF Total:                  {0,10:n}", HCFValue);
    WriteLine("First 35 Therms (* 1.5573): {0,10:n}", therms.First25Therms);
    WriteLine("First 20 Therms (* 1.2264): {0,10:n}", therms.Next15Therms);
    WriteLine("Above 40 Therms (* 0.9624): {0,10:n}", therms.Above40Therms);
    WriteLine("-----------------------------------------------------------");
    WriteLine("Water Usage Charges:        {0,10:n}", water);
    WriteLine("Sewer Charges:              {0,10:n}", sewer);
    WriteLine("===========================================================");
    WriteLine("Bill Values");
    WriteLine("-----------------------------------------------------------");
    WriteLine("Environment Charges:        {0,10:n}", environmentCharges);
    WriteLine("Service Charges:            {0,10:n}", serviceCharges);
    WriteLine("Total Charges:              {0,10:n}", totalCharges);
    WriteLine("Local Taxes:                {0,10:n}", localTaxes);
    WriteLine("State Taxes:                {0,10:n}", stateTaxes);
    WriteLine("-----------------------------------------------------------");
    WriteLine("Amount Due:                 {0,10:n}", amountDue);
    WriteLine("===========================================================");
    
    internal enum Classification { Residential, NonProfit, WaterIntensive, GeneralUse, Other }
  3. To execute, on the main menu, click Debug -> Start Without Debugging
  4. When requested, for the type of account, type 3 and press Enter
  5. For the Counter Reading Start, type 41 and press Enter
  6. For the Counter Reading End, type 246885 and press Enter
    Stellar Water Point
    ===========================================================
    To prepare an invoice, enter the following information
    Types of Accounts
    1. Residential Household
    2. Social/Non-Profit Organization
    3. Water Intensive Business (Laudromat, etc)
    4. General Business
    0. Other
    Enter Type of Account:         3
    -----------------------------------------------------------
    Counter Reading Start:         41
    Counter Reading End:           246885
    ===========================================================
    Stellar Water Point - Customer Invoice
    Account Type:               Water Intensive Business (Laudromat, Hair Salon, etc)
    ===========================================================
    Meter Reading
    -----------------------------------------------------------
    Counter Reading Start:              41
    Counter Reading End:            246885
    Total Gallons Consumed:         246844
    ===========================================================
    Therms Evaluation
    -----------------------------------------------------------
    HCF Total:                      330.01
    First 35 Therms (* 1.5573):      38.93
    First 20 Therms (* 1.2264):      18.40
    Above 40 Therms (* 0.9624):     279.10
    -----------------------------------------------------------
    Water Usage Charges:            336.43
    Sewer Charges:                  533.75
    ===========================================================
    Bill Values
    -----------------------------------------------------------
    Environment Charges:              3.53
    Service Charges:                 34.15
    Total Charges:                  907.86
    Local Taxes:                    748.98
    State Taxes:                     95.32
    -----------------------------------------------------------
    Amount Due:                   1,752.16
    ===========================================================
    
    Press any key to close this window . . .
  7. Return to your programming environment

Type and Inheritance

The objects you use in your applications have many origins. Some of them are from classes you create and some others are from existing classes. Another issue is that many classes are either derived from other classes, include abstract parent classes, and other classes implement one or more interfaces. Here is an example of different classes that implement the same interface:

public interface IAppliance
{
    public string? Make      { get; set; }
    public string? Model     { get; set; }
    public (double width, double height, double depth) Dimensions { get;set; }
    public double  Price     { get; set; }
}

public class Microwave : IAppliance
{
    public string? Make      { get; set; }
    public string? Model     { get; set; }
    public double Capacity   { get; set; }
    public int MenuOptions   { get; set; }
    public (double width, double height, double depth) Dimensions { get; set; }
    public double Price      { get; set; }
}

public class Dishwasher : IAppliance
{
    public string? Make      { get; set; }
    public string? Model     { get; set; }
    public int NumberOfRacks { get; set; }
    public (double width, double height, double depth) Dimensions { get; set; }
    public double Price      { get; set; }
}

public class Refrigerator : IAppliance
{
    public string? Make          { get; set; }
    public string? Model         { get; set; }
    public (double width,   double height, double depth) Dimensions { get; set; }
    public (double freezer, double refrigerator) Storage { get; set; }
    public bool    VoiceAssisted { get; set; }
    public double  Price         { get; set; }
}

You surely remember (from previous lessons) that from an abstract class or an interface, you can declare a variable but initialize it with a class derived from the abstract class or a class that implements the interface. Here are examples:

IAppliance micro = new Microwave()
{
    Make          = "Chefman",
    Model         = "RJ55-SS-9",
    Capacity      = 0.9, // Cubic Feet
    Dimensions    = (19.09, 11.54, 14.76), // W x H x D
    Price         = 88.98
};

IAppliance washer = new Dishwasher()
{
    Make          = "SPT",
    Model         = "SD-9254W",
    NumberOfRacks = 2,
    Dimensions    = (17.6, 32.4, 22.6), // W x H x D
    Price         = 459.95
};

IAppliance cold = new Refrigerator()
{
    Make          = "SMETA",
    Model         = "N/A",
    Dimensions    = (35.9, 69.9, 29), // W x H x D
    Storage       = (6.61, 15.89), //  cu. ft.
    VoiceAssisted = false,
    Price         = 1724.98
};

Some objects can have unpredictable origins, such as objects returned from functions, methods, libraries, etc. As a result, when a function or method receives an object as argument, it may be a good idea to first check the type of the object before performing any operation on it. You have many options.

As seen earlier, you can use the is keyword to check the type of an object that is passed as argument. This operator is even more valuable for object that share an ancestry. Consider the following example:

using static System.Console;

IAppliance micro = new Microwave()
{
    Make          = "Chefman",
    Model         = "RJ55-SS-9",
    Capacity      = 0.9, // Cubic Feet
    Dimensions    = (19.09, 11.54, 14.76), // W x H x D
    Price         = 88.98
};

IAppliance washer = new Dishwasher()
{
    Make          = "SPT",
    Model         = "SD-9254W",
    NumberOfRacks = 2,
    Dimensions    = (17.6, 32.4, 22.6), // W x H x D
    Price         = 459.95
};

IAppliance cold = new Refrigerator()
{
    Make          = "SMETA",
    Model         = "N/A",
    Dimensions    = (35.9, 69.9, 29), // W x H x D
    Storage       = (6.61, 15.89), //  cu. ft.
    VoiceAssisted = false,
    Price         = 1724.98
};

void Present(IAppliance iApp)
{
    if(iApp is Microwave)
    {
        WriteLine("Microwave Oven");
        WriteLine("---------------------------------------");
        WriteLine("Make:       {0}", iApp.Make);
        WriteLine("Model:      {0}", iApp.Model);
        WriteLine("Dimensions: {0}*W x {1}*H x {2}*D",
                  iApp.Dimensions.width,
                  iApp.Dimensions.height,
                  iApp.Dimensions.depth);
        WriteLine("Price:      {0}", iApp.Price);
        WriteLine("=======================================");
    }
    else
    {
        WriteLine("There is no machine to show.");
    }
}
WriteLine("=======================================");

Present(micro);

public interface IAppliance
{
    public string? Make      { get; set; }
    public string? Model     { get; set; }
    public (double width, double height, double depth) Dimensions { get;set; }
    public double  Price     { get; set; }
}
public class Microwave : IAppliance
{
    public string? Make      { get; set; }
    public string? Model     { get; set; }
    public double Capacity   { get; set; }
    public int MenuOptions   { get; set; }
    public (double width, double height, double depth) Dimensions { get; set; }
    public double Price      { get; set; }
}
public class Dishwasher : IAppliance
{
    public string? Make      { get; set; }
    public string? Model     { get; set; }
    public int NumberOfRacks { get; set; }
    public (double width, double height, double depth) Dimensions { get; set; }
    public double Price      { get; set; }
}
public class Refrigerator : IAppliance
{
    public string? Make          { get; set; }
    public string? Model         { get; set; }
    public (double width,   double height, double depth) Dimensions { get; set; }
    public (double freezer, double refrigerator) Storage { get; set; }
    public bool    VoiceAssisted { get; set; }
    public double  Price         { get; set; }
}

This would produce:

=======================================
Microwave Oven
---------------------------------------
Make:       Chefman
Model:      RJ55-SS-9
Dimensions: 19.09*W x 11.54*H x 14.76*D
Price:      88.98
=======================================

Press any key to close this window . . .

As we have already seen, if you pass an interface as argument, in the body of the function or method, you can access only the members of the interfaces. If you want to access the members of a class derived from an abstract class or a class that implements the interface, you should pass the type of the argument as object. Then, in the body of the function or method, you can use a conditional statement that checks the type of the argument. This can be done exactly as done above with the interface. A better alternative is the concept of a type pattern.

The primary formula to test the compatibility of an object is as follow:

condition-keyword(existing-object is class-type new-object)
    statement(s);

Once again, you start with a condition-keyword, usually if, followed by parentheses. In the parentheses, access the object that was passed as argument. Add a space and the is keyword. Specify the class of the class of which the argument is supposed to be. End with a name for an object. After the parentheses, you can create one or more statements that use the new object. In the statement(s), use the new object and access its members from it. Here are examples:

using static System.Console;

IAppliance micro = new Microwave()
{
    Make          = "Chefman",
    Model         = "RJ55-SS-9",
    Capacity      = 0.9, // Cubic Feet
    MenuOptions   = 16,
    Dimensions    = (19.09, 11.54, 14.76), // W x H x D
    Price         = 88.98
};

IAppliance washer = new Dishwasher()
{
    Make          = "SPT",
    Model         = "SD-9254W",
    NumberOfRacks = 2,
    Dimensions    = (17.6, 32.4, 22.6), // W x H x D
    Price         = 459.95
};

IAppliance cold = new Refrigerator()
{
    Make          = "SMETA",
    Model         = "N/A",
    Dimensions    = (35.9, 69.9, 29), // W x H x D
    Storage       = (6.61, 15.89), //  Cubic Feet
    VoiceAssisted = false,
    Price         = 1724.98
};

void Present(object iApp)
{
    if(iApp is Microwave mw)
    {
        WriteLine("Microwave Oven");
        WriteLine("----------------------------------------------");
        WriteLine("Make:              {0}", mw.Make);
        WriteLine("Model:             {0}", mw.Model);
        WriteLine("Capacity:          {0} cu. ft.", mw.Capacity);
        WriteLine("Menu Options:      {0}", mw.MenuOptions);
        WriteLine("Dimensions:        {0}*W x {1}*H x {2}*D",
                  mw.Dimensions.width,
                  mw.Dimensions.height,
                  mw.Dimensions.depth);
        WriteLine("Price:             ${0}", mw.Price);
        WriteLine("==============================================");
    }
    else if(iApp is Dishwasher dw)
    {
        WriteLine("Dishwasher");
        WriteLine("----------------------------------------------");
        WriteLine("Make:              {0}", dw.Make);
        WriteLine("Model:             {0}", dw.Model);
        WriteLine("Number of Racks:   {0}", dw.NumberOfRacks);
        WriteLine("Dimensions:        {0}*W x {1}*H x {2}*D",
                  dw.Dimensions.width,
                  dw.Dimensions.height,
                  dw.Dimensions.depth);
        WriteLine("Price:             ${0}", dw.Price);
        WriteLine("==============================================");
    }
    else if(iApp is Refrigerator frigo)
    {
        WriteLine("Refrigerator");
        WriteLine("----------------------------------------------");
        WriteLine("Make:              {0}", frigo.Make);
        WriteLine("Model:             {0}", frigo.Model);
        WriteLine("Dimensions:        {0}*W x {1}*H x {2}*D",
                  frigo.Dimensions.width,
                  frigo.Dimensions.height,
                  frigo.Dimensions.depth);
        WriteLine("Storage");
        WriteLine("     Freezer:      {0} cu. ft.",
                  frigo.Storage.freezer);
        WriteLine("     Refrigerator: {0} cu. ft.",
                  frigo.Storage.refrigerator);
        WriteLine("Price:             ${0}", frigo.Price);
        WriteLine("==============================================");
    }
    else
    {
        WriteLine("There is no object to show.");
    }
}
WriteLine("============================================");

Present(micro);
Present(washer);
Present(cold);

public interface IAppliance
{
    public string? Make      { get; set; }
    public string? Model     { get; set; }
    public (double width, double height, double depth) Dimensions { get;set; }
    public double  Price     { get; set; }
}
public class Microwave : IAppliance
{
    public string? Make      { get; set; }
    public string? Model     { get; set; }
    public double Capacity   { get; set; }
    public int MenuOptions   { get; set; }
    public (double width, double height, double depth) Dimensions { get; set; }
    public double Price      { get; set; }
}
public class Dishwasher : IAppliance
{
    public string? Make      { get; set; }
    public string? Model     { get; set; }
    public int NumberOfRacks { get; set; }
    public (double width, double height, double depth) Dimensions { get; set; }
    public double Price      { get; set; }
}
public class Refrigerator : IAppliance
{
    public string? Make          { get; set; }
    public string? Model         { get; set; }
    public (double width,   double height, double depth) Dimensions { get; set; }
    public (double freezer, double refrigerator) Storage { get; set; }
    public bool    VoiceAssisted { get; set; }
    public double  Price         { get; set; }
}

This would produce:

============================================
Microwave Oven
----------------------------------------------
Make:              Chefman
Model:             RJ55-SS-9
Capacity:          0.9 cu. ft.
Menu Options:      16
Dimensions:        19.09*W x 11.54*H x 14.76*D
Price:             $88.98
==============================================
Dishwasher
----------------------------------------------
Make:              SPT
Model:             SD-9254W
Number of Racks:   2
Dimensions:        17.6*W x 32.4*H x 22.6*D
Price:             $459.95
==============================================
Refrigerator
----------------------------------------------
Make:              SMETA
Model:             N/A
Dimensions:        35.9*W x 69.9*H x 29*D
Storage
     Freezer:      6.61 cu. ft.
     Refrigerator: 15.89 cu. ft.
Price:             $1724.98
==============================================

Press any key to close this window . . .

Switching a Pattern

Introduction

As we saw in the previous lessons, C# makes extensive use of the switch statement. Besides the way the switch keyword is used like the if...else conditional statements, C# adds some extended functionalities referred to as pattern matching.

Practical LearningPractical Learning: Processing a Switching Return

  1. Change the Program.cs document as follows:
    using static System.Console;
    
    (Classification iClass, string name) IdentifyAccount(string aType)
    {
        switch (aType)
        {
            case "1":
                return (Classification.Residential, "Residential Household");
            case "2":
                return (Classification.NonProfit, "Social/Non-Profit Organization");
            case "3":
                return (Classification.WaterIntensive, "Water Intensive Business (Laudromat, Hair Salon, etc)");
            case "4":
                return (Classification.GeneralUse, "General Business, Government");
            default:
                return (Classification.Other, "Other");
        }
    }
    
    double Subtract(in double a, in double b) => a - b;
    double CalculateHCFTotal(double gallons)  => gallons / 748.00;
    
    (double a, double b, double c) EvaluateTherms(in double hcf)
    {
        switch(hcf)
        {
            case > 40.00:
                return (25.00 * 1.5573, 15.00 * 1.2264, (hcf - 40.00) * 0.9624);
            case > 25.00:
                return (25.00 * 1.5573, (hcf - 25.00) * 1.2264, 0.00);
            default:
                return (hcf * 1.5573, 0.00, 0.00);
        }
    }
    
    double EvaluateSewerCharges(in double charges, in Classification @class)
    {
        switch (@class)
        {
            case Classification.Residential:
                return charges * 0.2528;
            case Classification.NonProfit:
                return charges * 0.0915;
            case Classification.WaterIntensive:
                return charges * 1.5865;
            case Classification.GeneralUse:
                return charges * 0.6405;
            default:
                return charges * 1.2125;
        }
    }
    
    double EvaluateEnvironmentCharges(in double charges, in Classification @class)
    {
        switch (@class)
        {
            case Classification.Residential:
                return charges * 0.0025;
            case Classification.NonProfit:
                return charges * 0.0015;
            case Classification.WaterIntensive:
                return charges * 0.0105;
            case Classification.GeneralUse:
                return charges * 0.0045;
            default:
                return charges * 0.0125;
        }
    }
    
    double EvaluateServiceCharges(in double charges, in Classification @class)
    {
        switch (@class)
        {
            case Classification.Residential:
                return charges * 0.0328;
            case Classification.NonProfit:
                return charges * 0.0115;
            case Classification.WaterIntensive:
                return charges * 0.1015;
            case Classification.GeneralUse:
                return charges * 0.0808;
            default:
                return charges * 0.1164;
        }
    }
    
    double AddTriple(in (double a, double b, double c) triple)      => triple.a + triple.b + triple.c;
    double Add3(in double a, in double b, in double c)              => a + b + c;
    double Add4(in double a, in double b, in double c, in double d) => a + b + c + d;
    
    double CalculateLocalTaxes(in double charges, in Classification @class)
    {
        switch (@class)
        {
            case Classification.Residential:
                return charges * 0.115;
            case Classification.NonProfit:
                return charges * 0.085;
            case Classification.WaterIntensive:
                return charges * 0.825;
            case Classification.GeneralUse:
                return charges * 0.315;
            default:
                return charges * 0.625;
        }
    }
    
    double CalculateStateTaxes(in double charges, in Classification @class)
    {
        switch (@class)
        {
            case Classification.Residential:
                return charges * 0.035;
            case Classification.NonProfit:
                return charges * 0.015;
            case Classification.WaterIntensive:
                return charges * 0.105;
            case Classification.GeneralUse:
                return charges * 0.065;
            default:
                return charges * 0.815;
        }
    }
    
    string GetCustomerType()
    {
        WriteLine("Stellar Water Point");
        WriteLine("===========================================================");
        WriteLine("To prepare an invoice, enter the following information");
        WriteLine("Types of Accounts");
        WriteLine("1. Residential Household");
        WriteLine("2. Social/Non-Profit Organization");
        WriteLine("3. Water Intensive Business (Laudromat, etc)");
        WriteLine("4. General Business");
        WriteLine("0. Other");
        Write("Enter Type of Account:         ");
        string answer = ReadLine()!;
        WriteLine("-----------------------------------------------------------");
    
        return answer;
    }
    
    int ReadCounter(out int start, out int end)
    {
        end   = 0;
        start = 0;
    
        try
        {
            Write("Counter Reading Start:         ");
            start = int.Parse(ReadLine()!);
        }
        catch(Exception ex) when (ex is FormatException fex)
        {
            WriteLine("The counter reading start value you entered is not valid.");
            WriteLine("The error produced is: " + fex.Message);
        }
    
        try
        {
            Write("Counter Reading End:           ");
            end = int.Parse(ReadLine()!);
        }
        catch (Exception ex) when (ex is FormatException fex)
        {
            WriteLine("The counter reading end value you entered is not valid.");
            WriteLine("The error produced is: " + fex.Message);
        }
    
        return 1_000;
    }
    
    int    readingEnd;
    int    readingStart;
    string acntType = GetCustomerType();
    
    _ = ReadCounter(out readingStart, out readingEnd);
    
    var account = IdentifyAccount(acntType);
    double gallons = Subtract(readingEnd, readingStart);
    double HCFValue = CalculateHCFTotal(gallons);
    (double First25Therms, double Next15Therms, double Above40Therms) therms = EvaluateTherms(HCFValue);
    double water = AddTriple(therms);
    double sewer = EvaluateSewerCharges(water, account.iClass);
    double environmentCharges = EvaluateEnvironmentCharges(water, account.iClass);
    double serviceCharges = EvaluateServiceCharges(water, account.iClass);
    double totalCharges = Add4(water, sewer, environmentCharges, serviceCharges);
    double localTaxes = CalculateLocalTaxes(totalCharges, account.iClass);
    double stateTaxes = CalculateStateTaxes(totalCharges, account.iClass);
    double amountDue = Add3(totalCharges, localTaxes, stateTaxes);
    
    WriteLine("===========================================================");
    WriteLine("Stellar Water Point - Customer Invoice");
    WriteLine("Account Type:               {0}", account.name);
    WriteLine("===========================================================");
    WriteLine("Meter Reading");
    WriteLine("-----------------------------------------------------------");
    WriteLine("Counter Reading Start:      {0,10}", readingStart);
    WriteLine("Counter Reading End:        {0,10}", readingEnd);
    WriteLine("Total Gallons Consumed:     {0,10}", gallons);
    WriteLine("===========================================================");
    WriteLine("Therms Evaluation");
    WriteLine("-----------------------------------------------------------");
    WriteLine("HCF Total:                  {0,10:n}", HCFValue);
    WriteLine("First 35 Therms (* 1.5573): {0,10:n}", therms.First25Therms);
    WriteLine("First 20 Therms (* 1.2264): {0,10:n}", therms.Next15Therms);
    WriteLine("Above 40 Therms (* 0.9624): {0,10:n}", therms.Above40Therms);
    WriteLine("-----------------------------------------------------------");
    WriteLine("Water Usage Charges:        {0,10:n}", water);
    WriteLine("Sewer Charges:              {0,10:n}", sewer);
    WriteLine("===========================================================");
    WriteLine("Bill Values");
    WriteLine("-----------------------------------------------------------");
    WriteLine("Environment Charges:        {0,10:n}", environmentCharges);
    WriteLine("Service Charges:            {0,10:n}", serviceCharges);
    WriteLine("Total Charges:              {0,10:n}", totalCharges);
    WriteLine("Local Taxes:                {0,10:n}", localTaxes);
    WriteLine("State Taxes:                {0,10:n}", stateTaxes);
    WriteLine("-----------------------------------------------------------");
    WriteLine("Amount Due:                 {0,10:n}", amountDue);
    WriteLine("===========================================================");
    
    internal enum Classification { Residential, NonProfit, WaterIntensive, GeneralUse, Other }
  2. To execute, on the main menu, click Debug -> Start Without Debugging
  3. When requested, for the type of account, type 8 and press Enter
  4. For the Counter Reading Start, type 882 and press Enter
  5. For the Counter Reading End, type 14729 and press Enter
    Stellar Water Point
    ===========================================================
    To prepare an invoice, enter the following information
    Types of Accounts
    1. Residential Household
    2. Social/Non-Profit Organization
    3. Water Intensive Business (Laudromat, etc)
    4. General Business
    0. Other
    Enter Type of Account:         8
    -----------------------------------------------------------
    Counter Reading Start:         882
    Counter Reading End:           14729
    ===========================================================
    Stellar Water Point - Customer Invoice
    Account Type:               Other
    ===========================================================
    Meter Reading
    -----------------------------------------------------------
    Counter Reading Start:             882
    Counter Reading End:             14729
    Total Gallons Consumed:          13847
    ===========================================================
    Therms Evaluation
    -----------------------------------------------------------
    HCF Total:                       18.51
    First 35 Therms (* 1.5573):      28.83
    First 20 Therms (* 1.2264):       0.00
    Above 40 Therms (* 0.9624):       0.00
    -----------------------------------------------------------
    Water Usage Charges:             28.83
    Sewer Charges:                   34.95
    ===========================================================
    Bill Values
    -----------------------------------------------------------
    Environment Charges:              0.36
    Service Charges:                  3.36
    Total Charges:                   67.50
    Local Taxes:                     42.19
    State Taxes:                     55.01
    -----------------------------------------------------------
    Amount Due:                     164.70
    ===========================================================
    
    Press any key to close this window . . .
  6. Return to your programming environment

Introduction to Switch Expressions

Consider the following function from things we learned in previous lessons:

using static System.Console;

int GetPayrollFrequency()
{
    int time;
    
    WriteLine("Enter the information to evaluate taxes");
    WriteLine("Frequency by which the payroll is processed:");
    WriteLine("1 - Weekly");
    WriteLine("2 - Biweekly");
    WriteLine("3 - Semimonthly");
    WriteLine("4 - Monthly");
    Write("Enter Payroll Frequency: ");
    time = int.Parse(ReadLine());

    return time;
}

double GetGrossSalary()
{
    double sal;

    Write("Gross Salary:            ");
    sal = double.Parse(ReadLine());

    return sal;
}

double EvaluateIncomeTax(int frequency, double sal)
{
    double incomeTax = 0.00;

    switch (frequency)
    {
        case 1:
            incomeTax = 271.08 + (sal * 24 / 100);
            break;
        case 2:
            incomeTax = 541.82 + (sal * 24 / 100);
            break;
        case 3:
            incomeTax = 587.12 + (sal * 24 / 100);
            break;
        case 4:
            incomeTax = 1174.12 + (sal * 24 / 100);
            break;
    }

    return incomeTax;
}

WriteLine("Payroll Evaluation");
WriteLine("============================================");
int period = GetPayrollFrequency();
WriteLine("--------------------------------------------");
double gs = GetGrossSalary();
double incomeTax = EvaluateIncomeTax(period, gs);

WriteLine("============================================");
WriteLine("Payroll Evaluation");
WriteLine("--------------------------------------------");
WriteLine("Gross Salary: {0,10:n}", gs);
WriteLine("Income Tax:   {0,10:n}", incomeTax);
WriteLine("============================================");

Instead of creating individual cases in a switch statement, you can use the => operator. To proceed, instead of a switch(expression) keyword with parentheses, replace it with the following formula:

return expression switch

Start the section with the return and the switch keyword without parentheses. Between those keywords, type the same type of expression we have used so far, such as a variable. Follow the line with a body delimited by curly brackets as seen so far with any switch statement. In that body, create a section for each possible case. This time, instead of the case keyword followed by a colon, use the => operator. On the right side the => operator, write the expression that the case clause is supposed to return. End the expression with a comma and proceed with the next case. After the closing curly bracket, you must end the whole statement with a semicolon. Here is an example:

using static System.Console;

int GetPayrollFrequency()
{
    int time;
    
    WriteLine("Enter the information to evaluate taxes");
    WriteLine("Frequency by which the payroll is processed:");
    WriteLine("1 - Weekly");
    WriteLine("2 - Biweekly");
    WriteLine("3 - Semimonthly");
    WriteLine("4 - Monthly");
    Write("Enter Payroll Frequency: ");
    time = int.Parse(ReadLine());

    return time;
}

double GetGrossSalary()
{
    double sal;

    Write("Gross Salary:            ");
    sal = double.Parse(ReadLine());

    return sal;
}

double EvaluateIncomeTax(int frequency, double sal)
{
    return frequency switch
    {
        1 => 271.08 + (sal * 24 / 100),
        2 => 541.82 + (sal * 24 / 100),
        3 => 587.12 + (sal * 24 / 100),
        4 => 1174.12 + (sal * 24 / 100)
    };
}

WriteLine("Payroll Evaluation");
WriteLine("============================================");
int period = GetPayrollFrequency();
WriteLine("--------------------------------------------");
double gs = GetGrossSalary();
double incomeTax = EvaluateIncomeTax(period, gs);

WriteLine("============================================");
WriteLine("Payroll Evaluation");
WriteLine("--------------------------------------------");
WriteLine("Gross Salary:{0,20:n}", gs);
WriteLine("Income Tax:  {0,20:n}", incomeTax);
WriteLine("============================================");

Here is an example of executing the program:

Payroll Evaluation
============================================
Enter the information to evaluate taxes
Frequency by which the payroll is processed:
1 - Weekly
2 - Biweekly
3 - Semimonthly
4 - Monthly
Enter Payroll Frequency: 1
--------------------------------------------
Gross Salary:            2466.88
============================================
Payroll Evaluation
--------------------------------------------
Gross Salary:            2,466.88
Income Tax:                863.13
============================================

Press any key to close this window . . .

The Default Case of a Switch Expression

As seen in the previous lesson, a typical switch statement can lead to a situation that doesn't fit any of the addressed cases, in which case you should have a default clause. If you are creating a switch expression, to create a default clause, use the underscore operator.

Practical LearningPractical Learning: Processing Switching Returns

  1. Change the code as follows:
    using static System.Console;
    
    (Classification iClass, string name) IdentifyAccount(string aType)
    {
        switch (aType)
        {
            case "1":
                return (Classification.Residential, "Residential Household");
            case "2":
                return (Classification.NonProfit, "Social/Non-Profit Organization");
            case "3":
                return (Classification.WaterIntensive, "Water Intensive Business (Laudromat, Hair Salon, etc)");
            case "4":
                return (Classification.GeneralUse, "General Business, Government");
            default:
                return (Classification.Other, "Other");
        }
    }
    
    double Subtract(in double a, in double b) => a - b;
    double CalculateHCFTotal(double gallons)  => gallons / 748.00;
    
    (double a, double b, double c) EvaluateTherms(in double hcf)
    {
        switch(hcf)
        {
            case > 40.00:
                return (25.00 * 1.5573, 15.00 * 1.2264, (hcf - 40.00) * 0.9624);
            case > 25.00:
                return (25.00 * 1.5573, (hcf - 25.00) * 1.2264, 0.00);
            default:
                return (hcf * 1.5573, 0.00, 0.00);
        }
    }
    
    double EvaluateSewerCharges(in double charges, in Classification @class)
    {
        return @class switch
        {
            Classification.Residential => charges * 0.2528,
            Classification.NonProfit => charges * 0.0915,
            Classification.WaterIntensive => charges * 1.5865,
            Classification.GeneralUse => charges * 0.6405,
            _ => charges * 1.2125,
        };
    }
    
    double EvaluateEnvironmentCharges(in double charges, in Classification @class)
    {
        return @class switch
        {
            Classification.Residential => charges * 0.0025,
            Classification.NonProfit => charges * 0.0015,
            Classification.WaterIntensive => charges * 0.0105,
            Classification.GeneralUse => charges * 0.0045,
            _ => charges * 0.0125,
        };
    }
    
    double EvaluateServiceCharges(in double charges, in Classification @class)
    {
        return @class switch
        {
            Classification.Residential => charges * 0.0328,
            Classification.NonProfit => charges * 0.0115,
            Classification.WaterIntensive => charges * 0.1015,
            Classification.GeneralUse => charges * 0.0808,
            _ => charges * 0.1164,
        };
    }
    
    double AddTriple(in (double a, double b, double c) triple)      => triple.a + triple.b + triple.c;
    double Add3(in double a, in double b, in double c)              => a + b + c;
    double Add4(in double a, in double b, in double c, in double d) => a + b + c + d;
    
    double CalculateLocalTaxes(in double charges, in Classification @class)
    {
        return @class switch
        {
            Classification.Residential => charges * 0.115,
            Classification.NonProfit => charges * 0.085,
            Classification.WaterIntensive => charges * 0.825,
            Classification.GeneralUse => charges * 0.315,
            _ => charges * 0.625,
        };
    }
    
    double CalculateStateTaxes(in double charges, in Classification @class)
    {
        return @class switch
        {
            Classification.Residential => charges * 0.035,
            Classification.NonProfit => charges * 0.015,
            Classification.WaterIntensive => charges * 0.105,
            Classification.GeneralUse => charges * 0.065,
            _ => charges * 0.815,
        };
    }
    
    string GetCustomerType()
    {
        WriteLine("Stellar Water Point");
        WriteLine("===========================================================");
        WriteLine("To prepare an invoice, enter the following information");
        WriteLine("Types of Accounts");
        WriteLine("1. Residential Household");
        WriteLine("2. Social/Non-Profit Organization");
        WriteLine("3. Water Intensive Business (Laudromat, etc)");
        WriteLine("4. General Business");
        WriteLine("0. Other");
        Write("Enter Type of Account:         ");
        string answer = ReadLine()!;
        WriteLine("-----------------------------------------------------------");
    
        return answer;
    }
    
    int ReadCounter(out int start, out int end)
    {
        end   = 0;
        start = 0;
    
        try
        {
            Write("Counter Reading Start:         ");
            start = int.Parse(ReadLine()!);
        }
        catch(Exception ex) when (ex is FormatException fex)
        {
            WriteLine("The counter reading start value you entered is not valid.");
            WriteLine("The error produced is: " + fex.Message);
        }
    
        try
        {
            Write("Counter Reading End:           ");
            end = int.Parse(ReadLine()!);
        }
        catch (Exception ex) when (ex is FormatException fex)
        {
            WriteLine("The counter reading end value you entered is not valid.");
            WriteLine("The error produced is: " + fex.Message);
        }
    
        return 1_000;
    }
    
    int    readingEnd;
    int    readingStart;
    string acntType = GetCustomerType();
    
    _ = ReadCounter(out readingStart, out readingEnd);
    
    var account = IdentifyAccount(acntType);
    double gallons = Subtract(readingEnd, readingStart);
    double HCFValue = CalculateHCFTotal(gallons);
    (double First25Therms, double Next15Therms, double Above40Therms) therms = EvaluateTherms(HCFValue);
    double water = AddTriple(therms);
    double sewer = EvaluateSewerCharges(water, account.iClass);
    double environmentCharges = EvaluateEnvironmentCharges(water, account.iClass);
    double serviceCharges = EvaluateServiceCharges(water, account.iClass);
    double totalCharges = Add4(water, sewer, environmentCharges, serviceCharges);
    double localTaxes = CalculateLocalTaxes(totalCharges, account.iClass);
    double stateTaxes = CalculateStateTaxes(totalCharges, account.iClass);
    double amountDue = Add3(totalCharges, localTaxes, stateTaxes);
    
    WriteLine("===========================================================");
    WriteLine("Stellar Water Point - Customer Invoice");
    WriteLine("Account Type:               {0}", account.name);
    WriteLine("===========================================================");
    WriteLine("Meter Reading");
    WriteLine("-----------------------------------------------------------");
    WriteLine("Counter Reading Start:      {0,10}", readingStart);
    WriteLine("Counter Reading End:        {0,10}", readingEnd);
    WriteLine("Total Gallons Consumed:     {0,10}", gallons);
    WriteLine("===========================================================");
    WriteLine("Therms Evaluation");
    WriteLine("-----------------------------------------------------------");
    WriteLine("HCF Total:                  {0,10:n}", HCFValue);
    WriteLine("First 35 Therms (* 1.5573): {0,10:n}", therms.First25Therms);
    WriteLine("First 20 Therms (* 1.2264): {0,10:n}", therms.Next15Therms);
    WriteLine("Above 40 Therms (* 0.9624): {0,10:n}", therms.Above40Therms);
    WriteLine("-----------------------------------------------------------");
    WriteLine("Water Usage Charges:        {0,10:n}", water);
    WriteLine("Sewer Charges:              {0,10:n}", sewer);
    WriteLine("===========================================================");
    WriteLine("Bill Values");
    WriteLine("-----------------------------------------------------------");
    WriteLine("Environment Charges:        {0,10:n}", environmentCharges);
    WriteLine("Service Charges:            {0,10:n}", serviceCharges);
    WriteLine("Total Charges:              {0,10:n}", totalCharges);
    WriteLine("Local Taxes:                {0,10:n}", localTaxes);
    WriteLine("State Taxes:                {0,10:n}", stateTaxes);
    WriteLine("-----------------------------------------------------------");
    WriteLine("Amount Due:                 {0,10:n}", amountDue);
    WriteLine("===========================================================");
    
    internal enum Classification { Residential, NonProfit, WaterIntensive, GeneralUse, Other }
  2. To execute, on the main menu, click Debug -> Start Without Debugging
  3. When requested, for the type of account, type 4 and press Enter
  4. For the Counter Reading Start, type 55755 and press Enter
  5. For the Counter Reading End, type 253579 and press Enter
    Stellar Water Point
    ===========================================================
    To prepare an invoice, enter the following information
    Types of Accounts
    1. Residential Household
    2. Social/Non-Profit Organization
    3. Water Intensive Business (Laudromat, etc)
    4. General Business
    0. Other
    Enter Type of Account:         4
    -----------------------------------------------------------
    Counter Reading Start:         55755
    Counter Reading End:           253579
    ===========================================================
    Stellar Water Point - Customer Invoice
    Account Type:               General Business, Government
    ===========================================================
    Meter Reading
    -----------------------------------------------------------
    Counter Reading Start:           55755
    Counter Reading End:            253579
    Total Gallons Consumed:         197824
    ===========================================================
    Therms Evaluation
    -----------------------------------------------------------
    HCF Total:                      264.47
    First 35 Therms (* 1.5573):      38.93
    First 20 Therms (* 1.2264):      18.40
    Above 40 Therms (* 0.9624):     216.03
    -----------------------------------------------------------
    Water Usage Charges:            273.36
    Sewer Charges:                  175.09
    ===========================================================
    Bill Values
    -----------------------------------------------------------
    Environment Charges:              1.23
    Service Charges:                 22.09
    Total Charges:                  471.76
    Local Taxes:                    148.61
    State Taxes:                     30.66
    -----------------------------------------------------------
    Amount Due:                     651.03
    ===========================================================
    
    Press any key to close this window . . .
  6. Return to your programming environment

Simplifying a Switch Expression

In our introduction to functions, we saw that, when a function returns a value, you can simplify its body by using the => operator. This functionality is also available for a switch expression. To apply it, after the parentheses of the function, remove the curly brackets of the function, replace the return keyword by the => operator, create the whole switch section, and end the whole statement with a semicolon. Here i5 an example:

using static System.Console;

int GetPayrollFrequency()
{
    int time;
    
    WriteLine("Enter the information to evaluate taxes");
    WriteLine("Frequency by which the payroll is processed:");
    WriteLine("1 - Weekly");
    WriteLine("2 - Biweekly");
    WriteLine("3 - Semimonthly");
    WriteLine("4 - Monthly");
    Write("Enter Payroll Frequency: ");
    time = int.Parse(ReadLine());

    return time;
}

double GetGrossSalary()
{
    double sal;

    Write("Gross Salary:            ");
    sal = double.Parse(ReadLine());

    return sal;
}

double EvaluateIncomeTax(int frequency, double sal) => frequency switch
{
    1 => 271.08 + (sal * 24 / 100),
    2 => 541.82 + (sal * 24 / 100),
    3 => 587.12 + (sal * 24 / 100),
    4 => 1174.12 + (sal * 24 / 100),
    _ => 0.00
};

WriteLine("Payroll Evaluation");
WriteLine("============================================");
int period = GetPayrollFrequency();
WriteLine("--------------------------------------------");
double gs = GetGrossSalary();
double incomeTax = EvaluateIncomeTax(period, gs);

WriteLine("============================================");
WriteLine("Payroll Evaluation");
WriteLine("--------------------------------------------");
WriteLine("Gross Salary:{0,20:n}", gs);
WriteLine("Income Tax:  {0,20:n}", incomeTax);
WriteLine("============================================");

Here is an example of running the program:

Payroll Evaluation
============================================
Enter the information to evaluate taxes
Frequency by which the payroll is processed:
1 - Weekly
2 - Biweekly
3 - Semimonthly
4 - Monthly
Enter Payroll Frequency: 2
--------------------------------------------
Gross Salary:            3317.93
============================================
Payroll Evaluation
--------------------------------------------
Gross Salary:            3,317.93
Income Tax:              1,338.12
============================================

Press any key to close this window . . .

Practical LearningPractical Learning: Simplifying a Switch Expression

  1. Change the code as follows:
    using static System.Console;
    
    . . .
    
    double EvaluateSewerCharges(in double charges, in Classification @class) => @class switch
    {
        Classification.Residential => charges * 0.2528,
        Classification.NonProfit => charges * 0.0915,
        Classification.WaterIntensive => charges * 1.5865,
        Classification.GeneralUse => charges * 0.6405,
        _ => charges * 1.2125,
    };
    
    double EvaluateEnvironmentCharges(in double charges, in Classification @class) => @class switch
    {
        Classification.Residential => charges * 0.0025,
        Classification.NonProfit => charges * 0.0015,
        Classification.WaterIntensive => charges * 0.0105,
        Classification.GeneralUse => charges * 0.0045,
        _ => charges * 0.0125,
    };
    
    double EvaluateServiceCharges(in double charges, in Classification @class) => @class switch
    {
        Classification.Residential => charges * 0.0328,
        Classification.NonProfit => charges * 0.0115,
        Classification.WaterIntensive => charges * 0.1015,
        Classification.GeneralUse => charges * 0.0808,
        _ => charges * 0.1164,
    };
    
    . . .
    
    double CalculateLocalTaxes(in double charges, in Classification @class) => @class switch
    {
        Classification.Residential => charges * 0.115,
        Classification.NonProfit => charges * 0.085,
        Classification.WaterIntensive => charges * 0.825,
        Classification.GeneralUse => charges * 0.315,
        _ => charges * 0.625
    };
    
    double CalculateStateTaxes(in double charges, in Classification @class) => @class switch
    {
        Classification.Residential => charges * 0.035,
        Classification.NonProfit => charges * 0.015,
        Classification.WaterIntensive => charges * 0.105,
        Classification.GeneralUse => charges * 0.065,
        _ => charges * 0.815,
    };
    
    . . .
  2. To execute, on the main menu, click Debug -> Start Without Debugging
  3. When requested, for the type of account, type 5 and press Enter
  4. For the Counter Reading Start, type 104 and press Enter
  5. For the Counter Reading End, type 285474 and press Enter
    Stellar Water Point
    ===========================================================
    To prepare an invoice, enter the following information
    Types of Accounts
    1. Residential Household
    2. Social/Non-Profit Organization
    3. Water Intensive Business (Laudromat, etc)
    4. General Business
    0. Other
    Enter Type of Account:         5
    -----------------------------------------------------------
    Counter Reading Start:         104
    Counter Reading End:           285474
    ===========================================================
    Stellar Water Point - Customer Invoice
    Account Type:               Other
    ===========================================================
    Meter Reading
    -----------------------------------------------------------
    Counter Reading Start:             104
    Counter Reading End:            285474
    Total Gallons Consumed:         285370
    ===========================================================
    Therms Evaluation
    -----------------------------------------------------------
    HCF Total:                      381.51
    First 35 Therms (* 1.5573):      38.93
    First 20 Therms (* 1.2264):      18.40
    Above 40 Therms (* 0.9624):     328.67
    -----------------------------------------------------------
    Water Usage Charges:            386.00
    Sewer Charges:                  468.02
    ===========================================================
    Bill Values
    -----------------------------------------------------------
    Environment Charges:              4.82
    Service Charges:                 44.93
    Total Charges:                  903.78
    Local Taxes:                    564.86
    State Taxes:                    736.58
    -----------------------------------------------------------
    Amount Due:                   2,205.21
    ===========================================================
    
    Press any key to close this window . . .
  6. Return to your programming environment and close Microsoft Visual Studio

Previous Copyright © 2001-2024, FunctionX Thursday 07 December 2024, 08:06 Next