Tuples and Switch Expressions

Processing a Tuple by Case

Remember that the cases of a switch statement can process a tuple. Here is an example adapted from an example in the previous lesson:

using static System.Console;

(int number, string name, bool allowedFullTime) member;

void RegisterEmployee()
{
    WriteLine("Enter the values about the employee");
    WriteLine("----------------------------------------------------------------------------");
    Write("Employee #:                                      ");
    member.number = int.Parse(ReadLine()!);
    Write("Employee Name:                                   ");
    member.name = ReadLine();
    Write("Is the employee allowed to work full-time (y/n): ");
    string answer = ReadLine();

    switch (answer)
    {
        case "y" or "Y":
            member.allowedFullTime = true;
            break;
        default:
            member.allowedFullTime = false;
            break;
    }
}
WriteLine("----------------------------------------------------------------------------");

string EvaluateStatus()
{
    string conclusion;

    switch (member)
    {
        case (975_947, "Alex Miller", false):
            conclusion = "The employee is not allowed to work overtime.";
            break;
        case (283_570, "Juliana Schwartz", true):
            conclusion = "This is a full-time employee who is allowed to work overtime.";
            break;
        case (283_624, "Arturo Garcia", true):
            conclusion = "This iemployee can work full-time.";
            break;
        default:
            conclusion = "The employee is not properly identified.";
            break;
    }

    return conclusion;
}

RegisterEmployee();

WriteLine("============================================================================");
WriteLine("Fun Department Store");
WriteLine("Employee Record");
WriteLine("----------------------------------------------------------------------------");
WriteLine($"Employee #:    {member.number}");
WriteLine($"Employee Name: {member.name}");
WriteLine($"Full-Time?     {member.allowedFullTime}");
WriteLine("----------------------------------------------------------------------------");
WriteLine("Conclusion:    {0}", EvaluateStatus());
WriteLine("============================================================================");

In this code, we used a local variable to return from the function. Of course, you can make each case return its value. This can be done as follows:

(int number, string name, bool allowedFullTime) member;

string EvaluateStatus()
{
    switch (member)
    {
        case (975_947, "Alex Miller", false):
            return "The employee is not allowed to work overtime.";
        case (283_570, "Juliana Schwartz", true):
            return "This is a full-time employee who is allowed to work overtime.";
        case (283_624, "Arturo Garcia", true):
            return "This iemployee can work full-time.";
        default:
            return "The employee is not properly identified.";
    }
}

To further reduce your code, you can convert the statement into a switch expression. This can be done as follows:

string EvaluateStatus()
{
    return member switch
    {
        (975_947, "Alex Miller", false) => "The employee is not allowed to work overtime.",
        (283_570, "Juliana Schwartz", true) => "This is a full-time employee who is allowed to work overtime.",
        (283_624, "Arturo Garcia", true) => "This iemployee can work full-time.",
        _ => "The employee is not properly identified.",
    };
}

Furthermore, you can replace the return keyword combined by the curly brackets with the => operator. This can be done as follows:

using static System.Console;

(int number, string name, bool allowedFullTime) member;

void RegisterEmployee()
{
    WriteLine("Enter the values about the employee");
    WriteLine("----------------------------------------------------------------------------");
    Write("Employee #:                                      ");
    member.number = int.Parse(ReadLine()!);
    Write("Employee Name:                                   ");
    member.name = ReadLine();
    Write("Is the employee allowed to work full-time (y/n): ");
    string answer = ReadLine();

    switch (answer)
    {
        case "y" or "Y":
            member.allowedFullTime = true;
            break;
        default:
            member.allowedFullTime = false;
            break;
    }
}
WriteLine("----------------------------------------------------------------------------");

string EvaluateStatus() => member switch
    {
        (975_947, "Alex Miller", false) => "The employee is not allowed to work overtime.",
        (283_570, "Juliana Schwartz", true) => "This is a full-time employee who is allowed to work overtime.",
        (283_624, "Arturo Garcia", true) => "This iemployee can work full-time.",
        _ => "The employee is not properly identified.",
    };

RegisterEmployee();

WriteLine("============================================================================");
WriteLine("Fun Department Store");
WriteLine("Employee Record");
WriteLine("----------------------------------------------------------------------------");
WriteLine($"Employee #:    {member.number}");
WriteLine($"Employee Name: {member.name}");
WriteLine($"Full-Time?     {member.allowedFullTime}");
WriteLine("----------------------------------------------------------------------------");
WriteLine("Conclusion:    {0}", EvaluateStatus());
WriteLine("============================================================================");

Practical LearningPractical Learning: Processing a Tuple by Case

  1. Start Microsoft Visual Studio.
    Create a C# Console App that supports the .NET 8.0 (Long-Term Support).
    Name the project as StellarWaterPoint6
  2. Change the Program.cs document as follows:
  3. 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) => @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 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) => @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,
    };
    
    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 }
  4. To execute, on the main menu, click Debug -> Start Without Debugging
  5. When requested, for the type of account, type 5 and press Enter
  6. For the Counter Reading Start, type 104 and press Enter
  7. 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 . . .
  8. Return to your programming environment

Expressing a Tuple

Consider a function as follows (from the previous lesson):

using static System.Console;

int GetViolation()
{
    WriteLine("Type of Traffic Violation");
    WriteLine("1 - Slow Driving");
    WriteLine("2 - Fast Driving");
    WriteLine("3 - Aggressive Driving");
    WriteLine("4 - Unknown - Other");
    WriteLine("--------------------------------------");
    Write("Type of violaction (1-4):      ");
    return int.Parse(ReadLine()!);
}

(int abc, string xyz) Evaluate(int problem)
{
    (int a, string b) result;

    switch (problem)
    {
        case 1:
            result = (0, "Slow Driving");
            break;
        case 2:
            result = (100, "Fast Driving");
            break;
        case 3:
            result = (125, "Aggressive Driving");
            break;
        default:
            result = (50, "Unknown - Other");
            break;
    }

    return result;
}

int infraction = GetViolation();
(int ticketAmount, string reason) ticket = Evaluate(infraction);

WriteLine("Ticket Summary");
WriteLine("======================================");
WriteLine("Traffic Violation: {0}", ticket.reason);
WriteLine("Ticket Amount:     {0}", ticket.ticketAmount);

We already know that we can reduce its code by making each case return its value. Here is an example:

(int abc, string xyz) Evaluate(int problem)
{
    switch (problem)
    {
        case 1:
            return (0, "Slow Driving");
        case 2:
            return (100, "Fast Driving");
        case 3:
            return (125, "Aggressive Driving");
        default:
            return (50, "Unknown - Other");
    }
}

If the cases of the switch statement return a tuple, you can reduce the code by creating a switch expression. Here is an example:

(int abc, string xyz) Evaluate(int problem)
{
    return problem switch
    {
        1 => (0, "Slow Driving"),
        2 => (100, "Fast Driving"),
        3 => (125, "Aggressive Driving"),
        _ => (50, "Unknown - Other")
    };
}

To further reduce the code, remember that you can replace the return keyword and the curly brackets of the function with the => operator. Here is an example:

using static System.Console;

int GetViolation()
{
    WriteLine("Type of Traffic Violation");
    WriteLine("1 - Slow Driving");
    WriteLine("2 - Fast Driving");
    WriteLine("3 - Aggressive Driving");
    WriteLine("4 - Unknown - Other");
    WriteLine("--------------------------------------");
    Write("Type of violaction (1-4):      ");
    return int.Parse(ReadLine()!);
}

(int abc, string xyz) Evaluate(int problem) =>
    problem switch
    {
        1 => (0, "Slow Driving"),
        2 => (100, "Fast Driving"),
        3 => (125, "Aggressive Driving"),
        _ => (50, "Unknown - Other")
    };

int infraction = GetViolation();
(int ticketAmount, string reason) ticket = Evaluate(infraction);

WriteLine("Ticket Summary");
WriteLine("======================================");
WriteLine("Traffic Violation: {0}", ticket.reason);
WriteLine("Ticket Amount:     {0}", ticket.ticketAmount);

Practical LearningPractical Learning: Switching Tuples

  1. Change the document as follows:
    using static System.Console;
    
    (Classification iClass, string name) IdentifyAccount(string aType)
    {
        return aType switch
        {
            "1" => (Classification.Residential, "Residential Household"),
            "2" => (Classification.NonProfit, "Social/Non-Profit Organization"),
            "3" => (Classification.WaterIntensive, "Water Intensive Business (Laudromat, Hair Salon, etc)"),
            "4" => (Classification.GeneralUse, "General Business, Government"),
            _ => (Classification.Other, "Other"),
        };
    }
    
    . . .
    
    (double a, double b, double c) EvaluateTherms(in double hcf)
    {
        return hcf switch
        {
            > 40.00 => (25.00 * 1.5573, 15.00 * 1.2264, (hcf - 40.00) * 0.9624),
            > 25.00 => (25.00 * 1.5573, (hcf - 25.00) * 1.2264, 0.00),
            _ => (hcf * 1.5573, 0.00, 0.00)
        };
    }
    
    . . .
  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 72 and press Enter
  5. For the Counter Reading End, type 417558 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:         72
    Counter Reading End:           417558
    ===========================================================
    Stellar Water Point - Customer Invoice
    Account Type:               Other
    ===========================================================
    Meter Reading
    -----------------------------------------------------------
    Counter Reading Start:              72
    Counter Reading End:            417558
    Total Gallons Consumed:         417486
    ===========================================================
    Therms Evaluation
    -----------------------------------------------------------
    HCF Total:                      558.14
    First 35 Therms (* 1.5573):      38.93
    First 20 Therms (* 1.2264):      18.40
    Above 40 Therms (* 0.9624):     498.65
    -----------------------------------------------------------
    Water Usage Charges:            555.98
    Sewer Charges:                  674.13
    ===========================================================
    Bill Values
    -----------------------------------------------------------
    Environment Charges:              6.95
    Service Charges:                 64.72
    Total Charges:                1,301.78
    Local Taxes:                    813.61
    State Taxes:                  1,060.95
    -----------------------------------------------------------
    Amount Due:                   3,176.34
    ===========================================================
    
    Press any key to close this window . . .
  6. Press Enter to close the window and return to your programming environment
  7. Start a new Console App that supports .NET 8.0 (Long-Term Support) with the project named StellarWaterPoint7
  8. To create a new folder, in the Solution Explorer, right-click StellarWaterPoint7 -> Add -> New Folder
  9. Type Models as the name of the new folder
  10. To create a class, in the Solution Explorer, right-click Models -> Add -> Class...
  11. Change the file Name to WaterBill
  12. Press Enter
  13. To create methods in the class, change the document as follows:
    namespace StellarWaterPoint7.Models
    {
        internal enum Classification
        {
            Residential,
            Laundromat,
            Restaurant,
            GeneralBusiness,
            NonProfit,
            Other
        }
    
        internal class WaterBill
        {
            private Classification category;
    
            public double CounterReadingStart { get; set; }
            public double CounterReadingEnd   { get; set; }
            public string? AccountType        { get; set; }
    
            public void IdentifyAccount(string number)
            {
                switch (number)
                {
                    case "1":
                        category = Classification.Residential;
                        AccountType= "Residential Household";
                        break;
                    case "2":
                        category = Classification.Laundromat;
                        AccountType = "Laudromat";
                        break;
                    case "3":
                        category = Classification.Restaurant;
                        AccountType= "Restaurant";
                        break;
                    case "4":
                        category = Classification.GeneralBusiness;
                        AccountType = "General Business";
                        break;
                    case "5":
                        category = Classification.NonProfit;
                        AccountType = "Social/Government/Non-Profit Organization";
                        break;
                    default:
                        category = Classification.Other;
                        AccountType = "Other";
                        break;
                }
            }
    
            public double CalculateGallons()
            {
                return CounterReadingEnd - CounterReadingStart;
            }
    
            public double CalculateHCFTotal()
            {
                // CCF: Centum Cubic Feet
                // HCF: Hundred Cubic Feet
                double gallons = CalculateGallons();
    
                return gallons / 748.00;
            }
    
            public (double First, double Next, double Above) EvaluateTherms()
            {
                /* Average Water Consumption
                 * 1. Residential
                 *    a. One Person: 80 gallons a day = 240 gallons a month = 7200 gallons in three months
                 *    b. Household of 2.64 people: 211.20 gallons a day = 6336 gallons a month = 19010 gallons in three months
                 * 2. Laudromat: 1820 gallons a day = 54600 gallons a month = 163800 gallons in three months, 450000 / 748 = 217.9144385
                 * 3. Restaurant: 3000 to 7000 gallons a day = 90000 to 210000 gallons a month = 270000 to 630000 gallons in three months => 163800 / 748 = 601.6042781 
                 * 4. Social/Non-Profit Organization: 80 gallons a day = 240 gallons a month = 7200 gallons in three months */
    
                double first;
                double next;
                double last;
    
                double hcf = CalculateHCFTotal();
    
                if (category == Classification.Residential)
                {
                    last = hcf / 4.00;
                    next  = (hcf - last) / 2.00;
                    first  = hcf - next;
                }
                else if (category == Classification.Laundromat)
                {
                    next = hcf / 2.00;
                    last = ((hcf - next) / 5.00) * 3.00;
                    first = hcf - last;
                }
                else if (category == Classification.Restaurant)
                {
                    next = hcf / 2.00;
                    last = ((hcf - next) / 5.00) * 2.00;
                    first = hcf - last;
                }
                else if (category == Classification.GeneralBusiness)
                {
                    next  = hcf / 3.00;
                    last  = (hcf - next) / 3.00;
                    first = hcf - last;
                }
                else if (category == Classification.NonProfit)
                {
                    last  = hcf / 6.00;
                    next  = (hcf - last) / 3.00;
                    first = hcf - next;
                }
                else
                {
                    last  = hcf / 5.00;
                    first = ((hcf - last) / 5.00) * 4.00;
                    next  = first - last;
                }
    
                return (first, next, last);
            }
    
            public double CalculateWaterCharges()
            {
                (double x, double y, double z) therms = EvaluateTherms();
                
                return therms.x + therms.y + therms.z;
            }
    
            public double EvaluateSewerCharges()
            {
                double result;
                double charges = CalculateWaterCharges();
    
                switch (category)
                {
                    case Classification.Residential:
                        result = charges * 0.35028;
                        break;
                    case Classification.Laundromat:
                        result = charges * 0.96817;
                        break;
                    case Classification.Restaurant:
                        result = charges * 0.88695;
                        break;
                    case Classification.GeneralBusiness:
                        result = charges * 0.76405;
                        break;
                    case Classification.NonProfit:
                        result = charges * 0.19185;
                        break;
                    default:
                        result = charges * 0.32125;
                        break;
                }
    
                return result;
            }
    
            public double CalculateStormCharges()
            {
                (double x, double y, double z) therms = EvaluateTherms();
    
                return (therms.x + therms.y + therms.z) / 98.735;
            }
    
            public double EvaluateEnvironmentCharges()
            {
                double result;
                double charges = CalculateWaterCharges();
    
                switch (category)
                {
                    case Classification.Residential:
                        result = charges * 0.00295;
                        break;
                    case Classification.Laundromat:
                        result = charges * 0.060105;
                        break;
                    case Classification.Restaurant:
                        result = charges * 0.059015;
                        break;
                    case Classification.GeneralBusiness:
                        result = charges * 0.030045;
                        break;
                    case Classification.NonProfit:
                        result = charges * 0.004805;
                        break;
                    default:
                        result = charges * 0.02285;
                        break;
                }
    
                return result;
            }
    
            public double EvaluateServiceCharges()
            {
                double result;
                double charges = CalculateWaterCharges();
    
                switch (category)
                {
                    case Classification.Residential:
                        result = charges * 0.00928;
                        break;
                    case Classification.Laundromat:
                        result = charges * 0.041015;
                        break;
                    case Classification.Restaurant:
                        result = charges * 0.039727;
                        break;
                    case Classification.GeneralBusiness:
                        result = charges * 0.027169;
                        break;
                    case Classification.NonProfit:
                        result = charges * 0.001175;
                        break;
                    default:
                        result = charges * 0.037164;
                        break;
                }
    
                return result;
            }
    
            public double CalculateTotalCharges()
            {
                double water = CalculateWaterCharges();
                double sewer = EvaluateServiceCharges();
                double storm = CalculateStormCharges();
                double environment = EvaluateEnvironmentCharges();
                double service = EvaluateServiceCharges();
    
                return water + sewer + storm  + environment + service;
            }
    
            public double CalculateLocalTaxes()
            {
                double result;
                double charges = CalculateTotalCharges();
    
                switch (category)
                {
                    case Classification.Residential:
                        result = charges * 0.01185;
                        break;
                    case Classification.Laundromat:
                        result = charges * 0.08257;
                        break;
                    case Classification.Restaurant:
                        result = charges * 0.05736;
                        break;
                    case Classification.GeneralBusiness:
                        result = charges * 0.03159;
                        break;
                    case Classification.NonProfit:
                        result = charges * 0.01422;
                        break;
                    default:
                        result = charges * 0.06295;
                        break;
                }
    
                return result;
            }
    
            public double CalculateStateTaxes()
            {
                double result;
                double charges = CalculateTotalCharges();
    
                switch (category)
                {
                    case Classification.Residential:
                        result = charges * 0.00385;
                        break;
                    case Classification.Laundromat:
                        result = charges * 0.023057;
                        break;
                    case Classification.Restaurant:
                        result = charges * 0.018053;
                        break;
                    case Classification.GeneralBusiness:
                        result = charges * 0.070605;
                        break;
                    case Classification.NonProfit:
                        result = charges * 0.05153;
                        break;
                    default:
                        result = charges * 0.05815;
                        break;
                }
    
                return result;
            }
    
            public double CalculateAmountDue()
            {
                return CalculateTotalCharges() + CalculateLocalTaxes() + CalculateStateTaxes();
            }
        }
    }
  14. In the Solution Explorer, right-click Program.cs and click Rename
  15. Type BillProcessing (to get InvoiceProcessing.cs) and press Enter
  16. Click the InvoiceProcessing.cs tab and change its document as follows:
    using StellarWaterPoint6.Models;
    using static System.Console;
    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. Laudromat");
        WriteLine("3. Restaurant");
        WriteLine("4. General Business");
        WriteLine("5. Social/Government/Non-Profit Organization");
        WriteLine("0. Unidentified or Unclassified Type of Organization");
        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);
    
    WaterBill bill = new WaterBill();
    
    bill.IdentifyAccount(acntType);
    bill.CounterReadingEnd   = readingEnd;
    bill.CounterReadingStart = readingStart;
    
    WriteLine("===========================================================");
    WriteLine("Stellar Water Point - Customer Invoice");
    WriteLine("Account Type:               {0}", bill.AccountType);
    WriteLine("===========================================================");
    WriteLine("Meter Reading");
    WriteLine("-----------------------------------------------------------");
    WriteLine("Counter Reading Start: {0,10}", bill.CounterReadingStart);
    WriteLine("Counter Reading End:   {0,10}", bill.CounterReadingEnd);
    WriteLine("Total Gallons Consumed:{0,10}", bill.CalculateGallons());
    WriteLine("HCF Total:             {0,10:n}", bill.CalculateHCFTotal());
    WriteLine("===========================================================");
    WriteLine("Therms Evaluation");
    WriteLine("-----------------------------------------------------------");
    WriteLine("First Tier:            {0,10:n}", bill.EvaluateTherms().First);
    WriteLine("Second Tier:           {0,10:n}", bill.EvaluateTherms().Next);
    WriteLine("Last Tier:             {0,10:n}", bill.EvaluateTherms().Above);
    WriteLine("===========================================================");
    WriteLine("Bill Values");
    WriteLine("-----------------------------------------------------------");
    WriteLine("Water Usage Charges:   {0,10:n}", bill.CalculateWaterCharges());
    WriteLine("Sewer Charges:         {0,10:n}", bill.EvaluateSewerCharges());
    WriteLine("Storm Charges:         {0,10:n}", bill.CalculateStormCharges());
    WriteLine("Environment Charges:   {0,10:n}", bill.EvaluateEnvironmentCharges());
    WriteLine("Service Charges:       {0,10:n}", bill.EvaluateServiceCharges());
    WriteLine("Total Charges:         {0,10:n}", bill.CalculateTotalCharges());
    WriteLine("-----------------------------------------------------------");
    WriteLine("Local Taxes:           {0,10:n}", bill.CalculateLocalTaxes());
    WriteLine("State Taxes:           {0,10:n}", bill.CalculateStateTaxes());
    WriteLine("-----------------------------------------------------------");
    WriteLine("Amount Due:            {0,10:n}", bill.CalculateAmountDue());
    WriteLine("===========================================================");
  17. To execute, on the main menu, click Debug -> Start Without Debugging
  18. When requested, for the type of account, type 1 and press Enter
  19. For the Counter Reading Start, type 92863 and press Enter
  20. For the Counter Reading Start, type 224926 and press Enter
    Stellar Water Point
    ===========================================================
    To prepare an invoice, enter the following information
    Types of Accounts
    1. Residential Household
    2. Laudromat
    3. Restaurant
    4. General Business
    5. Social/Government/Non-Profit Organization
    0. Unidentified or Unclassified Type of Organization
    Enter Type of Account:      1
    -----------------------------------------------------------
    Counter Reading Start:      92863
    Counter Reading End:        224926
    ===========================================================
    Stellar Water Point - Customer Invoice
    Account Type:               Residential Household
    ===========================================================
    Meter Reading
    -----------------------------------------------------------
    Counter Reading Start:      92863
    Counter Reading End:       224926
    Total Gallons Consumed:    132063
    HCF Total:                 176.55
    ===========================================================
    Therms Evaluation
    -----------------------------------------------------------
    First Tier:                110.35
    Second Tier:                66.21
    Last Tier:                  44.14
    ===========================================================
    Bill Values
    -----------------------------------------------------------
    Water Usage Charges:       220.69
    Sewer Charges:              77.30
    Storm Charges:               2.24
    Environment Charges:         0.65
    Service Charges:             2.05
    Total Charges:             227.68
    -----------------------------------------------------------
    Local Taxes:                 2.70
    State Taxes:                 0.88
    -----------------------------------------------------------
    Amount Due:                231.25
    ===========================================================
    
    Press any key to close this window . . .
  21. Return to your programming environment
  22. Click the WaterBill tab
  23. To replace the methods with properties, change the class as follows:
    namespace StellarWaterPoint6.Models
    {
        internal enum Classification
        {
            Residential,
            Laundromat,
            Restaurant,
            GeneralBusiness,
            NonProfit,
            Other
        }
    
        internal class WaterBill
        {
            private Classification category;
    
            public double CounterReadingStart { get; set; }
            public double CounterReadingEnd   { get; set; }
            public string? AccountType        { get; set; }
    
            public void IdentifyAccount(string number)
            {
                switch (number)
                {
                    case "1":
                        category = Classification.Residential;
                        AccountType= "Residential Household";
                        break;
                    case "2":
                        category = Classification.Laundromat;
                        AccountType = "Laudromat";
                        break;
                    case "3":
                        category = Classification.Restaurant;
                        AccountType= "Restaurant";
                        break;
                    case "4":
                        category = Classification.GeneralBusiness;
                        AccountType = "General Business";
                        break;
                    case "5":
                        category = Classification.NonProfit;
                        AccountType = "Social/Government/Non-Profit Organization";
                        break;
                    default:
                        category = Classification.Other;
                        AccountType = "Other";
                        break;
                }
            }
    
            public double Gallons
            {
                get
                {
                    return CounterReadingEnd - CounterReadingStart;
                }
            }
            
            // CCF: Centum Cubic Feet
            // HCF: Hundred Cubic Feet
            public double HCFTotal
            {
                get
                {
                    return Gallons / 748.00;
                }
            }
    
            public (double First, double Next, double Last) Therms
            {
                get
                {
                    /* Average Water Consumption
                     * 1. Residential
                     *    a. One Person: 80 gallons a day = 240 gallons a month = 7200 gallons in three months
                     *    b. Household of 2.64 people: 211.20 gallons a day = 6336 gallons a month = 19010 gallons in three months
                     * 2. Laudromat: 1820 gallons a day = 54600 gallons a month = 163800 gallons in three months, 450000 / 748 = 217.9144385
                     * 3. Restaurant: 3000 to 7000 gallons a day = 90000 to 210000 gallons a month = 270000 to 630000 gallons in three months => 163800 / 748 = 601.6042781 
                     * 4. Social/Non-Profit Organization: 80 gallons a day = 240 gallons a month = 7200 gallons in three months */
    
                    double first;
                    double next;
                    double last;
    
                    switch (category)
                    {
                        case Classification.Residential:
                            last  =  HCFTotal  / 4.00;
                            next  = (HCFTotal  - last) / 2.00;
                            first =  HCFTotal  - next;
                            break;
                        case Classification.Laundromat:
                            next  =   HCFTotal  / 2.00;
                            last  = ((HCFTotal  - next) / 5.00) * 3.00;
                            first =   HCFTotal  - last;
                            break;
                        case Classification.Restaurant:
                            next  =   HCFTotal / 2.00;
                            last  = ((HCFTotal - next) / 5.00) * 2.00;
                            first =   HCFTotal - last;
                            break;
                        case Classification.GeneralBusiness:
                            next  =  HCFTotal  / 3.00;
                            last  = (HCFTotal  - next) / 3.00;
                            first =  HCFTotal  - last;
                            break;
                        case Classification.NonProfit:
                            last  =  HCFTotal  / 6.00;
                            next  = (HCFTotal  - last) / 3.00;
                            first =  HCFTotal  - next;
                            break;
                        default:
                            last  =   HCFTotal / 5.00;
                            first = ((HCFTotal - last) / 5.00) * 4.00;
                            next  =   first    - last;
                            break;
                    }
    
                    return (first, next, last);
                }
            }
    
            public double WaterCharges
            {
                get
                {
                    return Therms.First + Therms.Next + Therms.Last;
                }
            }
    
            public double SewerCharges
            {
                get
                {
                    double result;
    
                    switch (category)
                    {
                        case Classification.Residential:
                            result = WaterCharges * 0.35028;
                            break;
                        case Classification.Laundromat:
                            result = WaterCharges * 0.96817;
                            break;
                        case Classification.Restaurant:
                            result = WaterCharges * 0.88695;
                            break;
                        case Classification.GeneralBusiness:
                            result = WaterCharges * 0.76405;
                            break;
                        case Classification.NonProfit:
                            result = WaterCharges * 0.19185;
                            break;
                        default:
                            result = WaterCharges * 0.32125;
                            break;
                    }
    
                    return result;
                }
            }
    
            public double StormCharges
            {
                get
                {
                    return (Therms.First + Therms.Next + Therms.Last) / 98.735;
                }
            }
    
            public double EnvironmentCharges
            {
                get
                {
                    double result;
    
                    switch (category)
                    {
                        case Classification.Residential:
                            result = WaterCharges * 0.00295;
                            break;
                        case Classification.Laundromat:
                            result = WaterCharges * 0.060105;
                            break;
                        case Classification.Restaurant:
                            result = WaterCharges * 0.059015;
                            break;
                        case Classification.GeneralBusiness:
                            result = WaterCharges * 0.030045;
                            break;
                        case Classification.NonProfit:
                            result = WaterCharges * 0.004805;
                            break;
                        default:
                            result = WaterCharges * 0.02285;
                            break;
                    }
    
                    return result;
                }
            }
    
            public double ServiceCharges
            {
                get
                {
                    double result;
    
                    switch (category)
                    {
                        case Classification.Residential:
                            result = WaterCharges * 0.00928;
                            break;
                        case Classification.Laundromat:
                            result = WaterCharges * 0.041015;
                            break;
                        case Classification.Restaurant:
                            result = WaterCharges * 0.039727;
                            break;
                        case Classification.GeneralBusiness:
                            result = WaterCharges * 0.027169;
                            break;
                        case Classification.NonProfit:
                            result = WaterCharges * 0.001175;
                            break;
                        default:
                            result = WaterCharges * 0.037164;
                            break;
                    }
    
                    return result;
                }
            }
    
            public double TotalCharges
            {
                get
                {
                    return WaterCharges + ServiceCharges + StormCharges + EnvironmentCharges + ServiceCharges;
                }
            }
    
            public double LocalTaxes
            {
                get
                {
                    double result;
    
                    switch (category)
                    {
                        case Classification.Residential:
                            result = TotalCharges * 0.01185;
                            break;
                        case Classification.Laundromat:
                            result = TotalCharges * 0.08257;
                            break;
                        case Classification.Restaurant:
                            result = TotalCharges * 0.05736;
                            break;
                        case Classification.GeneralBusiness:
                            result = TotalCharges * 0.03159;
                            break;
                        case Classification.NonProfit:
                            result = TotalCharges * 0.01422;
                            break;
                        default:
                            result = TotalCharges * 0.06295;
                            break;
                    }
    
                    return result;
                }
            }
    
            public double StateTaxes
            {
                get
                {
                    double result;
    
                    switch (category)
                    {
                        case Classification.Residential:
                            result = TotalCharges * 0.00385;
                            break;
                        case Classification.Laundromat:
                            result = TotalCharges * 0.023057;
                            break;
                        case Classification.Restaurant:
                            result = TotalCharges * 0.018053;
                            break;
                        case Classification.GeneralBusiness:
                            result = TotalCharges * 0.070605;
                            break;
                        case Classification.NonProfit:
                            result = TotalCharges * 0.05153;
                            break;
                        default:
                            result = TotalCharges * 0.05815;
                            break;
                    }
    
                    return result;
                }
            }
    
            public double AmountDue
            {
                get
                {
                    return TotalCharges + LocalTaxes + StateTaxes;
                }
            }
        }
    }
  24. Click the BillProcessing tab and change its document as follows:
    using static System.Console;
    using StellarWaterPoint6.Models;
    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. Laudromat");
        WriteLine("3. Restaurant");
        WriteLine("4. General Business");
        WriteLine("5. Social/Government/Non-Profit Organization");
        WriteLine("0. Unidentified or Unclassified Type of Organization");
        Write("Enter Type of Account:      ");
        string answer = ReadLine()!;
        WriteLine("-----------------------------------------------------------");
    
        return answer;
    }
    
    (int start, int end) ReadCounter()
    {
        Write("Counter Reading Start:      ");
        int counterStart = int.Parse(ReadLine()!);
        Write("Counter Reading End:        ");
        int counterEnd = int.Parse(ReadLine()!);
    
        return (counterStart, counterEnd);
    }
    
    string acntType = GetCustomerType();
    (int readingStart, int readingEnd) counter = ReadCounter();
    
    WaterBill bill = new WaterBill();
    
    bill.IdentifyAccount(acntType);
    bill.CounterReadingEnd   = counter.readingEnd;
    bill.CounterReadingStart = counter.readingStart;
    
    WriteLine("===========================================================");
    WriteLine("Stellar Water Point - Customer Invoice");
    WriteLine("Account Type:               {0}", bill.AccountType);
    WriteLine("===========================================================");
    WriteLine("Meter Reading");
    WriteLine("-----------------------------------------------------------");
    WriteLine("Counter Reading Start: {0,10}", bill.CounterReadingStart);
    WriteLine("Counter Reading End:   {0,10}", bill.CounterReadingEnd);
    WriteLine("Total Gallons Consumed:{0,10}", bill.Gallons);
    WriteLine("HCF Total:             {0,10:n}", bill.HCFTotal);
    WriteLine("===========================================================");
    WriteLine("Therms Evaluation");
    WriteLine("-----------------------------------------------------------");
    WriteLine("First Tier:          {0,10:n}", bill.Therms.First);
    WriteLine("Second Tier:         {0,10:n}", bill.Therms.Next);
    WriteLine("Last Tier:           {0,10:n}", bill.Therms.Last);
    WriteLine("===========================================================");
    WriteLine("Bill Values");
    WriteLine("-----------------------------------------------------------");
    WriteLine("Water Usage Charges:   {0,10:n}", bill.WaterCharges);
    WriteLine("Sewer Charges:         {0,10:n}", bill.SewerCharges);
    WriteLine("Storm Charges:         {0,10:n}", bill.StormCharges);
    WriteLine("Environment Charges:   {0,10:n}", bill.EnvironmentCharges);
    WriteLine("Service Charges:       {0,10:n}", bill.ServiceCharges);
    WriteLine("Total Charges:         {0,10:n}", bill.TotalCharges);
    WriteLine("-----------------------------------------------------------");
    WriteLine("Local Taxes:           {0,10:n}", bill.LocalTaxes);
    WriteLine("State Taxes:           {0,10:n}", bill.StateTaxes);
    WriteLine("-----------------------------------------------------------");
    WriteLine("Amount Due:            {0,10:n}", bill.AmountDue);
    WriteLine("===========================================================");
  25. To execute, on the main menu, click Debug -> Start Without Debugging
  26. When requested, for the type of account, type 2 and press Enter
  27. For the Counter Reading Start, type 92863 and press Enter
  28. For the Counter Reading Start, type 224926 and press Enter
    Stellar Water Point
    ===========================================================
    To prepare an invoice, enter the following information
    Types of Accounts
    1. Residential Household
    2. Laudromat
    3. Restaurant
    4. General Business
    5. Social/Government/Non-Profit Organization
    0. Unidentified or Unclassified Type of Organization
    Enter Type of Account:      2
    -----------------------------------------------------------
    Counter Reading Start:      92863
    Counter Reading End:        224926
    ===========================================================
    Stellar Water Point - Customer Invoice
    Account Type:               Laudromat
    ===========================================================
    Meter Reading
    -----------------------------------------------------------
    Counter Reading Start:      92863
    Counter Reading End:       224926
    Total Gallons Consumed:    132063
    HCF Total:                 176.55
    ===========================================================
    Therms Evaluation
    -----------------------------------------------------------
    First Tier:              123.59
    Second Tier:              88.28
    Last Tier:                52.97
    ===========================================================
    Bill Values
    -----------------------------------------------------------
    Water Usage Charges:       264.83
    Sewer Charges:             256.40
    Storm Charges:               2.68
    Environment Charges:        15.92
    Service Charges:            10.86
    Total Charges:             305.16
    -----------------------------------------------------------
    Local Taxes:                25.20
    State Taxes:                 7.04
    -----------------------------------------------------------
    Amount Due:                337.39
    ===========================================================
    
    Press any key to close this window . . .
  29. Return to your programming environment
  30. To reduce the code in the switch statements, change the WaterBill class as follows:
    namespace StellarWaterPoint7.Models
    {
        internal enum Classification
        {
            Residential,
            Laundromat,
            Restaurant,
            GeneralBusiness,
            NonProfit,
            Other
        }
    
        internal class WaterBill
        {
            private Classification category;
    
            public double  CounterReadingStart { get; set; }
            public double  CounterReadingEnd   { get; set; }
            public string? AccountType         { get; set; }
    
            public void IdentifyAccount(string number)
            {
                switch (number)
                {
                    case "1":
                        category = Classification.Residential;
                        AccountType = "Residential Household";
                        break;
                    case "2":
                        category = Classification.Laundromat;
                        AccountType = "Laudromat";
                        break;
                    case "3":
                        category = Classification.Restaurant;
                        AccountType = "Restaurant";
                        break;
                    case "4":
                        category = Classification.GeneralBusiness;
                        AccountType = "General Business";
                        break;
                    case "5":
                        category = Classification.NonProfit;
                        AccountType = "Social/Government/Non-Profit Organization";
                        break;
                    default:
                        category = Classification.Other;
                        AccountType = "Other";
                        break;
                }
            }
    
            public double Gallons => CounterReadingEnd - CounterReadingStart;
    
            public double HCFTotal
            {
                // CCF: Centum Cubic Feet
                // HCF: Hundred Cubic Feet
                get
                {
                    return Gallons / 748.00;
                }
                
            }
    
            public (double First, double Next, double Last) Therms
            {
                get
                {
                    /* Average Water Consumption
                     * 1. Residential
                     *    a. One Person: 80 gallons a day = 240 gallons a month = 7200 gallons in three months
                     *    b. Household of 2.64 people: 211.20 gallons a day = 6336 gallons a month = 19010 gallons in three months
                     * 2. Laudromat: 1820 gallons a day = 54600 gallons a month = 163800 gallons in three months, 450000 / 748 = 217.9144385
                     * 3. Restaurant: 3000 to 7000 gallons a day = 90000 to 210000 gallons a month = 270000 to 630000 gallons in three months => 163800 / 748 = 601.6042781 
                     * 4. Social/Non-Profit Organization: 80 gallons a day = 240 gallons a month = 7200 gallons in three months */
    
                    double first;
                    double next;
                    double last;
    
                    switch (category)
                    {
                        case Classification.Residential:
                            last = HCFTotal / 4.00;
                            next = (HCFTotal - last) / 2.00;
                            first = HCFTotal - next;
                            break;
                        case Classification.Laundromat:
                            next = HCFTotal / 2.00;
                            last = ((HCFTotal - next) / 5.00) * 3.00;
                            first = HCFTotal - last;
                            break;
                        case Classification.Restaurant:
                            next = HCFTotal / 2.00;
                            last = ((HCFTotal - next) / 5.00) * 2.00;
                            first = HCFTotal - last;
                            break;
                        case Classification.GeneralBusiness:
                            next = HCFTotal / 3.00;
                            last = (HCFTotal - next) / 3.00;
                            first = HCFTotal - last;
                            break;
                        case Classification.NonProfit:
                            last = HCFTotal / 6.00;
                            next = (HCFTotal - last) / 3.00;
                            first = HCFTotal - next;
                            break;
                        default:
                            last = HCFTotal / 5.00;
                            first = ((HCFTotal - last) / 5.00) * 4.00;
                            next = first - last;
                            break;
                    }
    
                    return (first, next, last);
                }
            }
    
            public double WaterCharges => Therms.First + Therms.Next + Therms.Last;
    
            public double SewerCharges
            {
                get
                {
                    switch (category)
                    {
                        case Classification.Residential:
                            return WaterCharges * 0.35028;
                        case Classification.Laundromat:
                            return WaterCharges * 0.96817;
                        case Classification.Restaurant:
                            return WaterCharges * 0.88695;
                        case Classification.GeneralBusiness:
                            return WaterCharges * 0.76405;
                        case Classification.NonProfit:
                            return WaterCharges * 0.19185;
                        default:
                            return WaterCharges * 0.32125;
                    }
                }
            }
    
            public double StormCharges
            {
                get
                {
                    return (Therms.First + Therms.Next + Therms.Last) / 98.735;
                }
            }
    
            public double EnvironmentCharges
            {
                get
                {
                    switch (category)
                    {
                        case Classification.Residential:
                            return WaterCharges * 0.00295;
                        case Classification.Laundromat:
                            return WaterCharges * 0.060105;
                        case Classification.Restaurant:
                            return WaterCharges * 0.059015;
                        case Classification.GeneralBusiness:
                            return WaterCharges * 0.030045;
                        case Classification.NonProfit:
                            return WaterCharges * 0.004805;
                        default:
                            return WaterCharges * 0.02285;
                    }
                }
            }
    
            public double ServiceCharges
            {
                get
                {
                    switch (category)
                    {
                        case Classification.Residential:
                            return WaterCharges * 0.00928;
                        case Classification.Laundromat:
                            return WaterCharges * 0.041015;
                        case Classification.Restaurant:
                            return WaterCharges * 0.039727;
                        case Classification.GeneralBusiness:
                            return WaterCharges * 0.027169;
                        case Classification.NonProfit:
                            return WaterCharges * 0.001175;
                        default:
                            return WaterCharges * 0.037164;
                    }
                }
            }
    
            public double TotalCharges
            {
                get
                {
                    return WaterCharges + ServiceCharges + StormCharges + EnvironmentCharges + ServiceCharges;
                }
            }
    
            public double LocalTaxes
            {
                get
                {
                    switch (category)
                    {
                        case Classification.Residential:
                            return TotalCharges * 0.01185;
                        case Classification.Laundromat:
                            return TotalCharges * 0.08257;
                        case Classification.Restaurant:
                            return TotalCharges * 0.05736;
                        case Classification.GeneralBusiness:
                            return TotalCharges * 0.03159;
                        case Classification.NonProfit:
                            return TotalCharges * 0.01422;
                        default:
                            return TotalCharges * 0.06295;
                    }
                }
            }
    
            public double StateTaxes
            {
                get
                {
                    switch (category)
                    {
                        case Classification.Residential:
                            return TotalCharges * 0.00385;
                        case Classification.Laundromat:
                            return TotalCharges * 0.023057;
                        case Classification.Restaurant:
                            return TotalCharges * 0.018053;
                        case Classification.GeneralBusiness:
                            return TotalCharges * 0.070605;
                        case Classification.NonProfit:
                            return TotalCharges * 0.05153;
                        default:
                            return TotalCharges * 0.05815;
                    }
                }
            }
    
            public double AmountDue => TotalCharges + LocalTaxes + StateTaxes;
        }
    }
  31. To execute the application to test it, press Ctrl + F5
  32. When requested, for the type of account, type 3 and press Enter
  33. For the Counter Reading Start, type 92863 and press Enter
  34. For the Counter Reading Start, type 224926 and press Enter
    Stellar Water Point
    ===========================================================
    To prepare an invoice, enter the following information
    Types of Accounts
    1. Residential Household
    2. Laudromat
    3. Restaurant
    4. General Business
    5. Social/Government/Non-Profit Organization
    0. Unidentified or Unclassified Type of Organization
    Enter Type of Account:      3
    -----------------------------------------------------------
    Counter Reading Start:      92863
    Counter Reading End:        224926
    ===========================================================
    Stellar Water Point - Customer Invoice
    Account Type:               Restaurant
    ===========================================================
    Meter Reading
    -----------------------------------------------------------
    Counter Reading Start:      92863
    Counter Reading End:       224926
    Total Gallons Consumed:    132063
    HCF Total:                 176.55
    ===========================================================
    Therms Evaluation
    -----------------------------------------------------------
    First Tier:              141.24
    Second Tier:              88.28
    Last Tier:                35.31
    ===========================================================
    Bill Values
    -----------------------------------------------------------
    Water Usage Charges:       264.83
    Sewer Charges:             234.89
    Storm Charges:               2.68
    Environment Charges:        15.63
    Service Charges:            10.52
    Total Charges:             304.19
    -----------------------------------------------------------
    Local Taxes:                17.45
    State Taxes:                 5.49
    -----------------------------------------------------------
    Amount Due:                327.13
    ===========================================================
    
    Press any key to close this window . . .
  35. Return to your programming environment
  36. To further improve the swith statements, change the class as follows:
    namespace StellarWaterPoint6.Models
    {
        internal enum Classification { Residential, Laundromat, Restaurant, GeneralBusiness, NonProfit, Other }
    
        internal class WaterBill
        {
            private Classification category;
    
            public double CounterReadingStart { get; set; }
            public double CounterReadingEnd   { get; set; }
            public string? AccountType        { get; set; }
    
            public void IdentifyAccount(string number)
            {
                switch (number)
                {
                    case "1":
                        category = Classification.Residential;
                        AccountType= "Residential Household";
                        break;
                    case "2":
                        category = Classification.Laundromat;
                        AccountType = "Laudromat";
                        break;
                    case "3":
                        category = Classification.Restaurant;
                        AccountType= "Restaurant";
                        break;
                    case "4":
                        category = Classification.GeneralBusiness;
                        AccountType = "General Business";
                        break;
                    case "5":
                        category = Classification.NonProfit;
                        AccountType = "Social/Government/Non-Profit Organization";
                        break;
                    default:
                        category = Classification.Other;
                        AccountType = "Other";
                        break;
                }
            }
    
            public double Gallons {
                get
                {
                    return CounterReadingEnd - CounterReadingStart;
                }
            }
            
            // CCF: Centum Cubic Feet
            // HCF: Hundred Cubic Feet
            public double HCFTotal { get { return Gallons / 748.00; } }
    
            public (double First, double Next, double Last) Therms
            {
                get
                {
                    /* Average Water Consumption
                     * 1. Residential
                     *    a. One Person: 80 gallons a day = 240 gallons a month = 7200 gallons in three months
                     *    b. Household of 2.64 people: 211.20 gallons a day = 6336 gallons a month = 19010 gallons in three months
                     * 2. Laudromat: 1820 gallons a day = 54600 gallons a month = 163800 gallons in three months, 450000 / 748 = 217.9144385
                     * 3. Restaurant: 3000 to 7000 gallons a day = 90000 to 210000 gallons a month = 270000 to 630000 gallons in three months => 163800 / 748 = 601.6042781 
                     * 4. Social/Non-Profit Organization: 80 gallons a day = 240 gallons a month = 7200 gallons in three months */
    
                    double first;
                    double next;
                    double last;
    
                    switch (category)
                    {
                        case Classification.Residential:
                            last  =  HCFTotal  / 4.00;
                            next  = (HCFTotal  - last) / 2.00;
                            first =  HCFTotal  - next;
                            break;
                        case Classification.Laundromat:
                            next  =   HCFTotal  / 2.00;
                            last  = ((HCFTotal  - next) / 5.00) * 3.00;
                            first =   HCFTotal  - last;
                            break;
                        case Classification.Restaurant:
                            next  =   HCFTotal / 2.00;
                            last  = ((HCFTotal - next) / 5.00) * 2.00;
                            first =   HCFTotal - last;
                            break;
                        case Classification.GeneralBusiness:
                            next  =  HCFTotal  / 3.00;
                            last  = (HCFTotal  - next) / 3.00;
                            first =  HCFTotal  - last;
                            break;
                        case Classification.NonProfit:
                            last  =  HCFTotal  / 6.00;
                            next  = (HCFTotal  - last) / 3.00;
                            first =  HCFTotal  - next;
                            break;
                        default:
                            last  =   HCFTotal / 5.00;
                            first = ((HCFTotal - last) / 5.00) * 4.00;
                            next  =   first    - last;
                            break;
                    }
    
                    return (first, next, last);
                }
            }
    
            public double WaterCharges => Therms.First + Therms.Next + Therms.Last;
    
            public double SewerCharges
            {
                get
                {
                    double result = category switch
                    {
                        Classification.Residential     => WaterCharges * 0.35028,
                        Classification.Laundromat      => WaterCharges * 0.96817,
                        Classification.Restaurant      => WaterCharges * 0.88695,
                        Classification.GeneralBusiness => WaterCharges * 0.76405,
                        Classification.NonProfit       => WaterCharges * 0.19185,
                        _                              => WaterCharges * 0.32125,
                    };
    
                    return result;
                }
            }
    
            public double StormCharges => (Therms.First + Therms.Next + Therms.Last) / 98.735;
    
            public double EnvironmentCharges
            {
                get
                {
                    double result = category switch
                    {
                        Classification.Residential     => WaterCharges * 0.002957,
                        Classification.Laundromat      => WaterCharges * 0.060803,
                        Classification.Restaurant      => WaterCharges * 0.059757,
                        Classification.GeneralBusiness => WaterCharges * 0.038059,
                        Classification.NonProfit       => WaterCharges * 0.004805,
                        _                              => WaterCharges * 0.022851,
                    };
    
                    return result;
                }
            }
    
            public double ServiceCharges
            {
                get => category switch
                {
                    Classification.Residential     => WaterCharges * 0.009282,
                    Classification.Laundromat      => WaterCharges * 0.041015,
                    Classification.Restaurant      => WaterCharges * 0.039727,
                    Classification.GeneralBusiness => WaterCharges * 0.027169,
                    Classification.NonProfit       => WaterCharges * 0.001175,
                    _                              => WaterCharges * 0.037164,
                };
            }
    
            public double TotalCharges
            {
                get
                {
                    return WaterCharges + ServiceCharges + StormCharges + EnvironmentCharges + ServiceCharges;
                }
            }
    
            public double LocalTaxes
            {
                get => category switch
                {
                    Classification.Residential     => TotalCharges * 0.013185,
                    Classification.Laundromat      => TotalCharges * 0.082537,
                    Classification.Restaurant      => TotalCharges * 0.057363,
                    Classification.GeneralBusiness => TotalCharges * 0.013159,
                    Classification.NonProfit       => TotalCharges * 0.014252,
                    _                              => TotalCharges * 0.016295,
                };
            }
    
            public double StateTaxes
            {
                get => category switch
                {
                    Classification.Residential     => TotalCharges * 0.005385,
                    Classification.Laundromat      => TotalCharges * 0.013057,
                    Classification.Restaurant      => TotalCharges * 0.011629,
                    Classification.GeneralBusiness => TotalCharges * 0.017005,
                    Classification.NonProfit       => TotalCharges * 0.015153,
                    _                              => TotalCharges * 0.001581,
                };
            }
    
            public double AmountDue { get { return TotalCharges + LocalTaxes + StateTaxes; } }
        }
    }
  37. To execute the application to test it, press Ctrl + F5
  38. When requested, for the type of account, type 4 and press Enter
  39. For the Counter Reading Start, type 92863 and press Enter
  40. For the Counter Reading Start, type 224926 and press Enter
    Stellar Water Point
    ===========================================================
    To prepare an invoice, enter the following information
    Types of Accounts
    1. Residential Household
    2. Laudromat
    3. Restaurant
    4. General Business
    5. Social/Government/Non-Profit Organization
    0. Unidentified or Unclassified Type of Organization
    Enter Type of Account:      4
    -----------------------------------------------------------
    Counter Reading Start:      92863
    Counter Reading End:        224926
    ===========================================================
    Stellar Water Point - Customer Invoice
    Account Type:               General Business
    ===========================================================
    Meter Reading
    -----------------------------------------------------------
    Counter Reading Start:      92863
    Counter Reading End:       224926
    Total Gallons Consumed:    132063
    HCF Total:                 176.55
    ===========================================================
    Therms Evaluation
    -----------------------------------------------------------
    First Tier:              137.32
    Second Tier:              58.85
    Last Tier:                39.23
    ===========================================================
    Bill Values
    -----------------------------------------------------------
    Water Usage Charges:       235.41
    Sewer Charges:             179.86
    Storm Charges:               2.38
    Environment Charges:         8.96
    Service Charges:             6.40
    Total Charges:             259.54
    -----------------------------------------------------------
    Local Taxes:                 3.42
    State Taxes:                 4.41
    -----------------------------------------------------------
    Amount Due:                267.37
    ===========================================================
    
    Press any key to close this window . . .
  41. Press E to close the window and return to your programming environment

When Switching a Value

Introduction

So far, we have seen that, when you are setting up a switch statement, create the desired case clauses in the switch section. The case keyword can be followed by either a constant value or an expression. Here are examples:

switch (number)
{
    case 1:
        selected = h;
        break;
    case 2:
        selected = he;
        break;
    case 3:
        selected = li;
        break;
}

Pattern matching consists of applying a condition to a case. In a case of a switch statement, you can include a conditional statement that compares its value to another to actually validate the case. This is done using the when keyword. The formula to follow is:

case value-or-expression when logical-expression: statement(s)

As mentioned already, the case is followed by a constant or an expression, The new keyword is when. It is followed by a logical expression.

We are starting a sample application named "Metropolitan Delivery". It is a (fictitious) company that owns various types of vehicles that are used by employees to deliver various types of merchandise. The pay of the employees is based on various factors. The deliveries made by the company are in three categories. The local covered includes the neighborhoods commonly known by employees and the ZIP codes are those close to the company's location. The metropolitan coverage is also an area familiar to the employees, including the cities in the proximity of less than 200 miles of the company's location. Any area beyond that distance is considered as nationwide. The employees are paid on the distance they cover to deliver a merchandise, but the rate depends on the category of coverage.

Here is an example:

using static System.Console;

double pieceworkRate = 0.50;
string coverageArea = "Unknown";

WriteLine("================================");
WriteLine("-- Metropolitan Delivery --");
WriteLine("================================");
WriteLine("Areas covered");
WriteLine("L - Local");
WriteLine("M - Metropolitan");
WriteLine("N - Nation");
Write("Enter the covered area: ");
string coverage = ReadLine();

if((coverage == "l") || (coverage == "L"))
    coverageArea  = "Local";
else if((coverage == "m") || (coverage == "M"))
    coverageArea = "Metropolitan";
else if((coverage == "n") || (coverage == "N"))
    coverageArea = "Nation";

Write("Miles driven:           ");
int miles = int.Parse(ReadLine()!);

switch(coverageArea)
{
    case "Local" when miles < 25:
        pieceworkRate = .46;
        break;
    case "Local" when miles >= 25 && miles < 65:
        pieceworkRate = .62;
        break;
    case "Local" when miles >= 65:
        pieceworkRate = .88;
        break;
    case "Metro":
        pieceworkRate = 1.42;
        break;
    case "Nation":
        pieceworkRate = 1.57;
        break;
}

double grossEarnings = miles * pieceworkRate;

WriteLine("================================");
WriteLine("-- Metropolitan Delivery --");
WriteLine("================================");
WriteLine($"Coverage:       {coverageArea}");
WriteLine($"Miles Driven:   {miles,8}");
WriteLine($"Piecework Rate: {pieceworkRate,8:f}");
WriteLine($"Gross Earnings: {grossEarnings,8:f}");
WriteLine("================================");

Here is an example of running the application

================================
-- Metropolitan Delivery --
================================
Areas covered
L - Local
M - Metropolitan
N - Nation
Enter the covered area: l
Miles driven:           22
================================
-- Metropolitan Delivery --
================================
Coverage:       Local
Miles Driven:         22
Piecework Rate:     0.46
Gross Earnings:    10.12
================================
Press any key to close this window . . .

Here is another example of running the application

================================
-- Metropolitan Delivery --
================================
Areas covered
L - Local
M - Metropolitan
N - Nation
Enter the covered area: L
Miles driven:           46
================================
-- Metropolitan Delivery --
================================
Coverage:       Local
Miles Driven:         46
Piecework Rate:     0.62
Gross Earnings:    28.52
================================
Press any key to close this window . . .

Press Enter to close the window and return to your programming environment

================================
-- Metropolitan Delivery --
================================
Areas covered
L - Local
M - Metropolitan
N - Nation
Enter the covered area: L
Miles driven:           148
================================
-- Metropolitan Delivery --
================================
Coverage:       Local
Miles Driven:        148
Piecework Rate:     0.88
Gross Earnings:   130.24
================================
Press any key to close this window . . .

Here is one more example of running the application

================================
-- Metropolitan Delivery --
================================
Areas covered
L - Local
M - Metropolitan
N - Nation
Enter the covered area: n
Miles driven:           148
================================
-- Metropolitan Delivery --
================================
Coverage:       Nation
Miles Driven:        148
Piecework Rate:     1.57
Gross Earnings:   232.36
================================
Press any key to close this window . . .

When Switching a Variable

After a case keyword, you can declare a variable of the same type as the value used in the parentheses of switch(). Follow the variable with the when keyword followed by a logical expression that equates the variable to the case value. The variable is "visible" only with its case. Therefore, you can use the same variable in different case sections.

When Patterning a Conditional Statement

The when expression is used to apply a conditional statement. It can consist of an expression that uses any of the Boolean operators we are familiar with. It may look as follows:

switch(number)
{
    case value-or-expression when number > 8:
        statement(s);
        break;
}

Patterning Different Types of Values

When using a switch statement, the values involved must be of the same type or compatible. Otherwise, you can find a way to convert them.

Practical LearningPractical Learning: Ending the Lesson


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