Fundamentals of Tuples

Introduction

A tuple is a series of values considered as an entity. A tuple is not a data type like an integer or a string, but it is used as if it were. This means that you can declare a variable as a tuple but it is not strictly used as the types of regular variables we have used so far.

A tuple is a combination of values where each value is recognized for itself. A value can be one of the primitive types we have already seen (int, bool, double, or string).

Practical LearningPractical Learning: Introducing Tuples

Creating a Tuple

You create a tuple as if you are declaring a variable as we have done so far. As a reminder, the formula to declare a variable is:

data-type variable-name;

In place of the data type, use some parentheses. For what inside the parentheses, you have various options. To start, in the parentheses of the tuple, you can write two or more data types. Those data types are separated by commas. Here are examples:

@{
    // A tuple made of integral numbers only
    (int, int)
    // A tuple made of strings only
    (string, string, string)
    // A tuple made of various types of values
    (int, string, double)
}

A value in a tuple can be called an item, a member, or an element (those are the names we will use in our lessons; all those names will mean the same thing).

In some cases, you can use an algebraic name to identify or define a tuple:

Naming a Tuple

After specifying the type of the tuple, like every variable, you must name it. This is done after the closing parenthesis. The name of a tuple follows the names of variables. After the name of the variable, add a semicolon. Here are examples:

@{
    (int, int) coordinates;
    (string, string, string) employeeName;
    (int, string, double) definition;
}

Initializing a Tuple: Binding Values to Elements of a Tuple

As is the case for other variables, before using a variable, it must have (a) value(s). This can be done by assigning a value to each member of the tuple. You have various options.

As one way to initialize a tuple, assign the desired values to it. As a reminder, the formula to declare and initialize a variable is:

data-type variable-name = value;

Based on this formula, to initialize a tuple, add the assignment operator after the name of the tuple. Add some parentheses. In the parentheses, specify the value of each member exactly in the order the data types appear in the declaration. Here is an example:

@{
    (string, string, string) students = ("Aaron", "Jennifer", "Yerimah");
}

As an alternative, you can first declare a variable on one line, and assign the desired values on another line. Here is an example:

@{
    (string, string, string) students;

    students = ("Aaron", "Jennifer", "Yerimah")
}

Introduction to Using a Tuple

Overview

The primary way you can use a tuple is to present its values to the user. To do this in a razor page, create an HTML tag and use an @ symbol to access the variable. Here is an example:

@page
@model PracticalLearning.Pages.HumanResourcesModel
@{
    (string, string) employee = ("Robert", "Ewell");
}

<p>Employee: @employee</p>

This would produce:

Employee: (Robert, Ewell)

Accessing an Element of a Tuple

The elements of a tuple each has a name. By default, the first element is named Item1, the second element is named Item2, and so on. These names are specified automatically by the compiler when you create a tuple. To access an element of a tuple, type the variable name of a tuple, a period, and the name of the element. If you are using Microsoft Visual Studio to develop your application, when you type the tuple variable and a period, the intellisense will display the names of the elements of the tuple. Here is an example:

Accessing an Element of a Tuple

By accessing each element like that, you can initialize a tuple by assigning a value to each element. Here is an example:

@page
@model PracticalLearning.Pages.HumanResourcesModel
@{
    (int, string, string, double) contractor;

    contractor.Item1 = 947_069;
    contractor.Item2 = "Gerard";
    contractor.Item3 = "Soundjok";
    contractor.Item4 = 68426;
}

In the same way, you can access an element to present its value to the user. Here are examples:

@page
@model PracticalLearning.Pages.HumanResourcesModel
@{
    (int, string, string, double) contractor;

    contractor.Item1 = 947_069;
    contractor.Item2 = "Gerard";
    contractor.Item3 = "Soundjok";
    contractor.Item4 = 68426;
}

<pre>Employee Record
---------------------------
Employee #:    @contractor.Item1
First Name:    @contractor.Item2
Last Name:     @contractor.Item3
Yearly Salary: @contractor.Item4
===========================</pre>

This would produce:

Employee Record
------------------------
Employee #:    947069
First Name:    Gerard
Last Name:     Soundjok
Yearly Salary: 68426
========================

Naming the Members of a Tuple

As seen already, when creating a tuple, you can simply specify the data types of the members of the tuple. As an option, you can name 0, some, or all members of the tuple. To name a member, after the data type of a member, add a space and a name. Again, you are free to choose what member(s) to name. Here are examples:

@page
@model PracticalLearning.Pages.TuplesModel
@{
    (double, string) x;
    (int horizontal, int) coordinates;
    (string first_name, string, string last_name) employeeName;
    (int employeeNumber, string employment_Status, double yearlysalary) definition;
}

You can then initialize the tuple. Once again, to access an element of a tuple, type the name of the tuple variable, a period, and the element you want. Again, if you are using Microsoft Visual Studio, the intellisense will display the names of the elements of the tuple. Here are two examples where some elements were named and some were not:

Accessing an Element of a Tuple

Accessing an Element of a Tuple

When accessing the items of a tuple, if you had named an element, you can use either its default name (Item1, Item2, etc) or the name you had specified.

Other Techniques of Initializing a Tuple

A Value from a Variable

We already know that, when you create a tuple, sooner or later, you must specify the value of each member. The value of a member can come from a variable. Here is an example:

@page
@model PracticalLearning.Pages.TuplesModel
@{
    int emplNbr = 138_475;

    (int emplNumber, string firstName, string lastName) employee = (emplNbr, "Gwendolyn", "Valance");
}

<pre>Employee Record
--------------------------------
Employee #:   @employee.emplNumber
Full Name:    @employee.Item2 @employee.lastName
================================</pre>

This would produce:

Employee Record
--------------------------------
Employee #:   138475
Full Name:    Gwendolyn Valance
================================

A Tuple Item from an Expression

The value of a member of a tuple can come from an expression. Here is an example:

@page
@model PracticalLearning.Pages.TuplesModel
@{
    int emplNbr = 138_475;
    double weeklySalary = 22.27;
    string fName = "Christoffer";
    string lName = "Prize";

    (int emplNumber, string fullName, double salary) employee = (emplNbr, fName + " " + lName, weeklySalary * 40);
}

<pre>Employee Record
--------------------------------
Employee #:    @employee.emplNumber
Full Name:     @employee.fullName
Weekly Salary: @employee.salary
================================</pre>

This would produce:

Employee Record
---------------------------------------
Employee #:    138475
Full Name:     Christoffer Prize
Weekly Salary: 890.8
=======================================

A var Tuple

You can declare a tuple variable using the var keyword. Remember that if you declare a variable with that keyword, you must immediately initialize it. Therefore, the formula to declare a var tuple is:

var variable-name = ( item_1, item_2, item_x);

In the parentheses, you can specify the desired value for each member of the tuple. Here is an example:

var staff = (392507, "Gertrude", "Ngovayang", 96275);

You can then access the elements of the tuple. Once again in this case, by default, the first element is named Item1, the second is name Item2, and so on. Here are examples:

@page
@model PracticalLearning.Pages.TuplesModel
@{
    var staff = (392507, "Gertrude", "Ngovayang", 96275);
}

<pre>Employee Record
-----------------------------
Employee #:     @staff.Item1
First Name:     @staff.Item2
Last Name:      @staff.Item3
Yearly  Salary: @staff.Item4
=============================</pre>

This would produce:

Employee Record
------------------------
Employee #:    392507
First Name:    Gertrude
Last Name:     Ngovayang
Yearly Salary: 96275
========================

We saw that, when creating a tuple, you can specify the name of an element. If you are creating a var tuple, to specify the name of an element, in the parentheses, type that name, a colon, and the value of the element. Here are examples:

var staff = (392507, firstName: "Gertrude", "Ngovayang", salary: 96275);

This time too, you can access an element either by its ordinal name or the name you had given it, if any. Here are examples:

@page
@model PracticalLearning.Pages.TuplesModel
@{
    var staff = (emplNumber: 394806, "Denis", lastName: "Merchand", 96275, fullTime: true);
}

<pre>Employee Record
-----------------------------
Employee #:         @staff.Item1
First Name:         @staff.Item2
Last Name:          @staff.lastName
Yearly  Salary:     @staff.Item4
Employed Full-Time: @staff.Item5
=============================</pre>

This would produce:

Employee Record
-----------------------------
Employee #:         394806
First Name:         Denis
Last Name:          Merchand
Yearly  Salary:     96275
Employed Full-Time: True
=============================

Tuples and Conditional Statements

Introduction

A tuple is a series of values treated as an entity but where each item can be accessed on its own. Once you have accessed an item, you can perform a comparison on it. Here is an example:

@page
@model PracticalLearning.Pages.TuplesModel
@{
    (int memNbr, string name, string category, int fee) member;

    member.memNbr = 938_405;
    member.name     = "Matthew Groeder";
    member.category = "Adult";
    member.fee      = -1;

    if (member.category == "Child")
        member.fee = 0;
    if (member.category == "Yound Adult")
        member.fee = 15;
    if (member.category == "Adult")
        member.fee = 45;
    if (member.category == "Senior")
        member.fee = 25;
}

<pre>+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
Club Membership
==============================================
Member Information
----------------------------------------------
Membership #:    @member.memNbr
Member Name:     @member.name
Membership Type: @member.category
----------------------------------------------
Membership Fee:  @member.fee
==============================================</pre>

This would produce:

+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
Club Membership
==============================================
Member Information
----------------------------------------------
Membership #:    938405
Member Name:     Matthew Groeder
Membership Type: Adult
----------------------------------------------
Membership Fee:  $45
==============================================

Switching a Tuple

Since an item of a tuple primarily holds a value, you can use it in a switching conditional statement. Here is an example:

@page
@model PracticalLearning.Pages.TuplesModel
@{
    (int memNbr, string name, string category, int fee) member;
    
    member.memNbr   = 297_624;
    member.name     = "Catherine Simms";
    member.category = "Senior";
    member.fee      = -1;
    
    switch (member.category)
    {
        case "Yound Adult":
            member.fee = 15;
            break;
        case "Adult":
            member.fee = 45;
            break;
        case "Senior":
            member.fee = 25;
            break;
        default:
            member.fee = 0;
            break;
    }
}

<pre>+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
Club Membership
==============================================
Member Information
----------------------------------------------
Membership #:    @member.memNbr
Member Name:     @member.name
Membership Type: @member.category
----------------------------------------------
Membership Fee:  @member.fee
==============================================</pre>

This would produce:

+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
Club Membership
==============================================
Member Information
----------------------------------------------
Membership #:    297624
Member Name:     Catherine Simms
Membership Type: Senior
----------------------------------------------
Membership Fee:  25
==============================================

In reality, because a tuple is some kind of a variable, you can use it as the values to consider in a switch statement. To start, pass the name of the tuple to the parentheses of switch(). Then for each case, provide a complete set of values in parentheses about the tuple. You can then process different cases normally. Here is an example:

@page
@model PracticalLearning.Pages.TuplesModel
@{
    (int number, string name, bool allowedFullTime) member;

    member.number = 608624;
    member.name   = "Arturo Garcia";
    string answer = "Y";
    
    switch (answer)
    {
        case "y" or "Y":
            member.allowedFullTime = true;
            break;
        default:
            member.allowedFullTime = false;
            break;
    }
}

@switch(member)
{
    case (975_947, "Alex Miller", false):
        <p>The employee is not allowed to work overtime.</p>
        break;

    case (283_570, "Juliana Schwartz", true):
        <p>This is a full-time employee who is allowed to work overtime.</p>
        break;

    case (283_624, "Arturo Garcia", true):
        <p>This iemployee can work full-time.</p>
        break;
    default:
        <p>The employee is not properly identified.</p>
        break;
}

This would produce:

The employee is not properly identified.

Here is another version of the program:

@page
@model PracticalLearning.Pages.TuplesModel
@{
    (int number, string name, bool allowedFullTime) member;

    member.number = 283_570;
    member.name   = "Juliana Schwartz";
    string answer = "y";
    
    switch (answer)
    {
        case "y" or "Y":
            member.allowedFullTime = true;
            break;
        default:
            member.allowedFullTime = false;
            break;
    }
}

@switch(member)
{
    case (975_947, "Alex Miller", false):
        <p>The employee is not allowed to work overtime.</p>
        break;

    case (283_570, "Juliana Schwartz", true):
        <p>This is a full-time employee who is allowed to work overtime.</p>
        break;

    case (283_624, "Arturo Garcia", true):
        <p>This iemployee can work full-time.</p>
        break;
    default:
        <p>The employee is not properly identified.</p>
        break;
}

This would produce:

This is a full-time employee who is allowed to work overtime.

Tuples and Functions

A Value from a Function

Earlier, we saw that you can create a function that returns a value, you can call that function and assign its return value to a variable, then use that variable as an item of a tuple. Here is the example we used:

@page
@model PracticalLearning.Pages.TuplesModel
@{
    double EvaluateSalary(double hourly)
    {
        return hourly * 40;
    }
    
    int emplNbr = 138_475;
    double weeklySalary = 22.27;
    string fName = "Christoffer";
    string lName = "Prize";
    
    double sal = EvaluateSalary(weeklySalary);
    
    (int emplNumber, string fullName, double salary) employee = (emplNbr, fName + " " + lName, sal);
}

<pre>Employee Record
----------------------------------
Employee #:    @employee.emplNumber
Full Name:     @employee.fullName
Weekly Salary: @employee.salary
==================================</pre>

This would produce:

Employee Record
----------------------------------
Employee #:    138475
Full Name:     Christoffer Prize
Weekly Salary: 890.8
==================================

The value of a member of a tuple can come from a function. In the above example, we first called a function and assigned its return value to a value. This may be necessary if you need to use the return value many times. Otherwise, you can call the function where the value of the tuple element is accessed. Here is an example:

@page
@model PracticalLearning.Pages.TuplesModel
@{
    double EvaluateSalary(double hourly)
    {
        return hourly * 40;
    }
    
    int emplNbr = 138_475;
    double weeklySalary = 22.27;
    string fName = "Christoffer";
    string lName = "Prize";
    
    (int emplNumber,
     string fullName,
     double salary) employee = (emplNbr, fName + " " + lName,
     EvaluateSalary(weeklySalary));
}

<pre>Employee Record
----------------------------------
Employee #:    @employee.emplNumber
Full Name:     @employee.fullName
Weekly Salary: @employee.salary
==================================</pre>

Passing a Tuple as Parameter

If you have a group of values that you want a function to process, instead of passing those values individually, you can package those values in a tuple. In other words, you can create a function that takes a tuple as argument.

To make a function process a tuple, when creating the function, in its parentheses, type the parentheses for a tuple, followed by a name for the parameter. In the parentheses of the tuple, enter the data type of each member of the tuple and separate them with commas Here is an example:

void Calculate((int, double, string) parameter)
{
}

In the body of the function, to access the tuple, use the name of the parameter. To access a member of the tuple, in the body of the function, type the name of the parameter, a period, and the name of the desired member. Here is an example:

@page
@model PracticalLearning.Pages.TuplesModel
@{
    (double price, int reduction) itemInfo;
    (int number, string name, double price, int days) storeItem;

    storeItem.number = 9370592;
    storeItem.name = "Summer Casual V-Neck Floral Dress";
    storeItem.days = 38;
    storeItem.price = 98.85;
    int discountRate = EvaluateDiscountRate(storeItem.days);

    itemInfo.price = storeItem.price;
    itemInfo.reduction = discountRate;

    double discountedAmount = EvaluateDiscountAmount(itemInfo);
    double markedPrice = storeItem.price - discountedAmount;

    string strOriginalPrice  = $"{storeItem.price:f}";
    string strDiscountAmount = $"{discountedAmount:f}";
    string strMarkedPrice    = $"{markedPrice:f}";
}

@functions{
    int EvaluateDiscountRate(int days)
    {
        int discountRate = 0;

        if (days > 70)
            discountRate = 70;
        else if (days > 50)
            discountRate = 50;
        else if (days > 30)
            discountRate = 35;
        else if (days > 15)
            discountRate = 15;

        return discountRate;
    }
    
    double EvaluateDiscountAmount((double cost, int rate) value)
    {
        double discountAmount = value.cost * value.rate / 100.00;
        
        return discountAmount;
    }
}

<pre>===================================================
Fun Department Store
---------------------------------------------------
Item #:          @storeItem.number
Item Name:       @storeItem.name
Days in Store:   @storeItem.days
Original Price:  @strOriginalPrice
---------------------------------------------------
Discount Rate:   @discountRate%
Discount Amount: @strDiscountAmount
Marked Price:    @strMarkedPrice
===================================================</pre>

This produce:

===================================================
Fun Department Store
---------------------------------------------------
Item #:          9370592
Item Name:       Summer Casual V-Neck Floral Dress
Days in Store:   38
Original Price:  98.85
---------------------------------------------------
Discount Rate:   35%
Discount Amount: 34.60
Marked Price:    64.25
===================================================

As seen with using tuples on a function, if you provided only the data types of the members of the tuple parameter, access the members with their incrementing names: Item1, Item2, etc. As an alternative, you can provide a name for one or more members of the tuple parameters.

Passing Many Tuples to a Method

We saw that you can pass a tuple to a method. In the same way, you can pass a combination of a tuple and parameters of regular types to a method. Here is an example:

@functions{
    void Examine(int id, (string title, string description) issue, bool resolved)
    {

    }
}

In the same way, you can create a function or method that takes more than one tuple as parameters.

Returning a Tuple

Instead of a regular single value, a function can be made to return a tuple, which is a combination of values. This is one of the most important features of tuples.

When creating a function, to indicate that it must produce a tuple, on the left side of the name of the function, type a tuple. Here is an example:

@functions{
    (string, int, string, double) Summarize()
    {

    }
}

On the last line, type the return keyword, followed by a tuple that uses a combination of values of the exact same type declared for the function. Here is an example

@functions{
    (string, int, string, double) Summarize()
    {
        return ("John", 10, "Doe", 1.00);
    }
}

Otherwise, in the body of the function, you can perform any operation you want. For example, you can declare variables of any type and use them any way you want. In fact, you can return a tuple that uses such local variables. Here is an example:

@functions{
    (string, int, string, double) Summarize()
    {
        double salary = 52_846;
        int    code   = 293_704;
        string first  = "John", last = "Doe";

        return (first, code, last, salary);
    }
}

The return tuple can also use one or more expressions. Here is an example:

@functions{
    (int, string, double) Summarize()
    {
        double hourSalary = 22.86;
        int    code       = 293_704;
        string first      = "John", last = "Doe";

        /* Yearly Salary = Hourly Salary *  8 (= Daily Salary)
                                         *  5 (= Weekly Salary)
                                         *  4 (= Monthly Salary)
                                         * 12 (= Yearly Salary)   */

        return (code, first + " " + last, hourSalary * 8 * 5 * 4 * 12);
    }
}

Combining Tuples in Declaring Tuple Variables

We have already seen how to create a tuple. Here is an example:

@{
    (string, int, string, double) pay_scale) contractor;
}

In reality, every element of a tuple is an entity of its own. This means that you can create a tuple where an element of a tuple would be. Here are examples of tuples included in a tuple:

@{
    ((string, string), int, (int, int, int), bool, (string, double)) contractor;
}

If the creation of a tuple is very long, you can create the element on different lines, like this:

@{
    ((string, string),
        int, 
        (int, int, int),
        bool,
        (string, double)
    ) contractor;
}

Or like this:

@{
    (
        (string, string),
        int,
        (int, int, int),
        bool,
        (string, double)
    ) contractor;
}

In fact, the following notation works as well:

@{
    (
        (
      	     string,
            string
        ),
        int,
            (
            int,
            int,
            int
            ),
        bool,
        (
      	     string,
            double
        )
    ) contractor;
}

Once again, you are not required to name the elements of the tuples, but you must admit that the above tuple can be difficult to read. First, you must identify the primary element and how many they are. If you don't name them, the incremental default names given to them are Item1, Item2, etc.

To access an element that is from an internal tuple, first access its parent position.. This can be done as follows:

Tuples and Properties

Then use a period to access the internal element. This can be done as follows:

Tuples and Properties

As you can see, to make your tuple easy to read, it may be a good idea to name it elements. If you want, you can name just the primary elements. Here is an example:

((string, string) full_name, double height, (int, int, int) date_hired, bool recommended, (string, double) pay_scale) contractor;

On the other hand, you can name only the internal elements. Here are examples:

((string fname, string lname), double, (int month, int day, int year), bool, (string status, double rate)) contractor;

Otherwise, you can, and should, name all elements, primary and internal. Here are examples:

@{
    (
    (string fname, string lname) full_name,
    (int month, int day, int year) date_hired,
    (string status, double rate) pay_scale
    ) contractor;
}

You can then conveniently access the tuples and their elements using their explicit names. Here is an example:

@{
    (
        (string fname, string lname) full_name,
        double hourly_salary, 
        (int month, int day, int year) date_hired,
        bool is_full_time, 
        (string status, int rate) pay_scale
    ) contractor;

    // Accessing items individually
    contractor.hourly_salary    = 22.85;
    contractor.full_name.fname  = "Peter";
    contractor.full_name.lname  = "Jacobson";
    contractor.date_hired.month = 4;
    contractor.date_hired.day   = 18;
    contractor.date_hired.year  = 2022;
    contractor.is_full_time     = true;
    contractor.pay_scale.status = "Full-Time";
    contractor.pay_scale.rate   = 3;

    // Accessing items individual tuples
    contractor.full_name = ("Jennifer", "Sopngui");
    contractor.date_hired = (10, 6, 2022);
    contractor.hourly_salary = 14.05;
    contractor.is_full_time = true;
    contractor.pay_scale = ("Part-Time", 1);

    // Accessing the whole tuple
    contractor = (("Paul", "Chancellor"), 27.96, (07, 02,2022), true, ("Unknown", 2));
}

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 a code in a previous section:

@page
@model PracticalLearning.Pages.TuplesModel
@{
    (int number, string name, bool allowedFullTime) member;
    member.number = 975_947;
    member.name = "Alex Miller";
    member.allowedFullTime = false;
    
    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;
    }
}

<h3>Fun Department Store</h3>
<pre>==================================================================
Employee Record
------------------------------------------------------------------
Employee #:    @member.number
Employee Name: @member.name
Full-Time?     @member.allowedFullTime
------------------------------------------------------------------
Conclusion:    @EvaluateStatus()
==================================================================</pre>

This would produce:

Fun Department Store

==================================================================
Employee Record
------------------------------------------------------------------
Employee #:    975947
Employee Name: Alex Miller
Full-Time?     False
------------------------------------------------------------------
Conclusion:    The employee is not allowed to work overtime.
==================================================================

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:

@page
@model PracticalLearning.Pages.TuplesModel
@{
    (int number, string name, bool allowedFullTime) member;
    
    member.number = 975_947;
    member.name = "Alex Miller";
    member.allowedFullTime = true;
    
    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.";
        }
    }
}

<h3>Fun Department Store</h3>
<pre>==================================================================
Employee Record
------------------------------------------------------------------
Employee #:    @member.number
Employee Name: @member.name
Full-Time?     @member.allowedFullTime
------------------------------------------------------------------
Conclusion:    @EvaluateStatus()
==================================================================</pre>

This would produce:

Fun Department Store

==================================================================
Employee Record
------------------------------------------------------------------
Employee #:    975947
Employee Name: Alex Miller
Full-Time?     True
------------------------------------------------------------------
Conclusion:    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:

@page
@model PracticalLearning.Pages.TuplesModel
@{
    (int number, string name, bool allowedFullTime) member;

    member.number = 283_570;
    member.name = "Arturo Garcia";
    member.allowedFullTime = true;

    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."
    };
}

<h3>Fun Department Store</h3>
<pre>==================================================================
Employee Record
------------------------------------------------------------------
Employee #:    @member.number
Employee Name: @member.name
Full-Time?     @member.allowedFullTime
------------------------------------------------------------------
Conclusion:    @EvaluateStatus()
==================================================================</pre>

Returning a Tuple

Consider a function as follows:

@page
@model PracticalLearning.Pages.TuplesModel
@{
    int violationType = 0;

    (int ticketAmount, string reason) ticket = Evaluate(violationType);
}

@functions{
    (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;
    }
}

<pre>Ticket Summary
======================================
Traffic Violation: @ticket.reason
Ticket Amount:     @ticket.ticketAmount
======================================</pre>

This would produce:

Ticket Summary
======================================
Traffic Violation: Unknown - Other
Ticket Amount:     50
======================================

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:

@functions{
    (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:

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

Practical LearningPractical Learning: Switching Tuples

  1. Change the document as follows:
    using static System.Console;
    
    int violation;
    int drivingSpeed;
    int postedSpeedLimit;
    
    string strPeriod;
    string strTypeOfViolation;
    (int pay, string issue) ticketIssue;
    (int amount, string name) roadIssue;
    
    string IdentifyPeriodofDay()
    {
        WriteLine("Periods");
        WriteLine("1 - Monday-Friday - Night (7PM - 6AM)");
        WriteLine("2 - Monday-Friday - Morning Rush Hour (6AM - 9AM)");
        WriteLine("3 - Monday-Friday - Regular Time (9AM - 3PM)");
        WriteLine("4 - Monday-Friday - Afternoon Rush Hour (3PM - 7PM)");
        WriteLine("5 - Weekend (Saturday-Sunday) and Holidays");
        WriteLine("----------------------------------------------------------");
        Write("Period of the infraction (1-5): ");
        int period = int.Parse(ReadLine());
        
        switch (period)
        {
            case 1:
                return "Monday-Friday - Night (7PM - 6AM)";   
            case 2:
                return "Monday-Friday - Morning Rush Hour (6AM - 9AM)";
            default: // case 3:
                return "Monday-Friday - Regular Time (9AM - 3PM)";
            case 4:
                return "Monday-Friday - Afternoon Rush Hour (3PM - 7PM)";
            case 5:
                return "Weekend (Saturday-Sunday) and Holidays";    
        }
    }
    
    string IdentifyRoadType()
    {
        WriteLine("Type of Road");
        WriteLine("1 - Interstate (Ex. I95)");
        WriteLine("2 - Federal/State Highway (Ex. US50)");
        WriteLine("3 - State Road (Ex. TN22, MD410)");
        WriteLine("4 - County/Local Road (Ex. Randolph Rd, Eusebio Ave, Abena Blvd) or Local - Unknown (Ex. Sterling Str, Garvey Court)");
        WriteLine("----------------------------------------------------------");
        Write("Type of road (1-4):             ");
        int roadType = int.Parse(ReadLine());
    
        return roadType switch
        {
            1 => "Interstate",
            2 => "Federal/State Highway",
            3 => "State Road",
            _ => "County/Local Road, Others"
        };
    }
    
    (int a, string b) IdentifyTrafficIssue()
    {
        WriteLine("Types of issues");
        WriteLine("0 - No particular issues");
        WriteLine("1 - Health issues");
        WriteLine("2 - Driving while sleeping");
        WriteLine("3 - Driving while using an electronic device");
        WriteLine("4 - Driving under the influence (of alcohol, drugs, intoxicating products, etc)");
        Write("Type of issue (0-4):            ");
        int typeOfIssue = int.Parse(ReadLine());
        
        switch(typeOfIssue)
        {
            case 1:
                return (0, "Health issues");
            case 2:
                return (150, "Driving while sleeping");
            case 3:
                return (100, "Driving while using an electronic device");
            case 4:
                return (350, "Driving under the influence (alcohol, drugs, intoxicating products, or else)");
            default:
                return (0, "No particular issues relatted to the traffic violation");
        }
    }
    
    (int a, string b) EvaluateInterstateTraffic()
    {
        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):      ");
        violation = int.Parse(ReadLine());
    
        switch (violation)
        {
            case 1:
                return (0, "Slow Driving");
            case 2:
                return (100, "Fast Driving");
            case 3:
                return (125, "Aggressive Driving");
            default:
                return (50, "Unknown - Other");
        }
    }
    
    (int a, string b) EvaluateHighwayTraffic()
    {
        WriteLine("Type of Traffic Violation");
        WriteLine("1 - Slow Driving");
        WriteLine("2 - Fast Driving");
        WriteLine("3 - Aggressive Driving");
        WriteLine("4 - Driving Through Steady Red Light");
        WriteLine("5 - Driving Through Flashing Red Light");
        WriteLine("6 - Red Light Right Turn Without Stopping");
        WriteLine("7 - Unknown - Other");
        WriteLine("----------------------------------------------------------");
        Write("Type of violaction (1-7):      ");
        violation = int.Parse(ReadLine());
    
        return violation switch
        {
            1 => (0, "Slow Driving"),
            2 => (65, "Fast Driving"),
            3 => (75, "Aggressive Driving"),
            4 => (105, "Driving Through Steady Red Light"),
            5 => (35, "Driving Through Flashing Red Light"),
            6 => (25, "Red Light Right Turn Without Stopping"),
            _ => (5, "Unknown - Other")
        };
    }
    
    (int a, string b) EvaluateLocalTraffic()
    {
        WriteLine("Type of Traffic Violation");
        WriteLine("1 - Slow Driving");
        WriteLine("2 - Fast Driving");
        WriteLine("3 - Aggressive Driving");
        WriteLine("4 - Driving Through Steady Red Light");
        WriteLine("5 - Driving Through Flashing Red Light");
        WriteLine("6 - Red Light Right Turn Without Stopping");
        WriteLine("7 - Driving Through Stop Sign Without Stopping");
        WriteLine("8 - Unknown - Other");
        WriteLine("----------------------------------------------------------");
        Write("Type of violaction (1-8):      ");
        violation = int.Parse(ReadLine());
    
        return violation switch
        {
            1 => ( 0, "Slow Driving"),
            2 => (35, "Fast Driving"),
            3 => (55, "Aggressive Driving"),
            4 => (65, "Driving Through Steady Red Light"),
            5 => (55, "Driving Through Flashing Red Light"),
            6 => (35, "Red Light Right Turn Without Stopping"),
            7 => (15, "Driving Through Stop Sign Without Stopping"),
            _ => ( 5, "Unknown - Other")
        };
    }
    
    WriteLine("Traffic System System");
    WriteLine("==========================================================");
    strPeriod = IdentifyPeriodofDay();
    WriteLine("==========================================================");
    string strRoadType = IdentifyRoadType();
    WriteLine("==========================================================");
    
    Write("Posted Speed Limit:             ");
    postedSpeedLimit = int.Parse(ReadLine());
    Write("Driving Speed:                  ");
    drivingSpeed = int.Parse(ReadLine());
    WriteLine("==========================================================");
    ticketIssue = IdentifyTrafficIssue();
    WriteLine("==========================================================");
    
    if (strRoadType == "Interstate")
    {
        roadIssue = EvaluateInterstateTraffic();
    }
    else if (strRoadType == "Federal/State Highway")
    {
        roadIssue = EvaluateHighwayTraffic();
    }
    else
    {
        roadIssue = EvaluateLocalTraffic();
    }
    
    WriteLine("==========================================================");
    WriteLine("Traffic Ticket Summary");
    WriteLine("----------------------------------------------------------");
    WriteLine("Period of the day:  {0}", strPeriod);
    WriteLine("Road Type:          {0}", strRoadType);
    WriteLine("Posted Speed Limit: {0}", postedSpeedLimit);
    WriteLine("Driving Speed:      {0}", drivingSpeed);
    WriteLine("Type of Issue:      {0}", ticketIssue.issue);
    WriteLine("     Base Ticket:   {0}", ticketIssue.pay);
    WriteLine("Violation Type:     {0}", roadIssue.name);
    WriteLine("     Addition Fee:  {0}", roadIssue.amount);
    WriteLine("----------------------------------------------------------");
    WriteLine("Ticket Amount:      {0}", ticketIssue.pay + roadIssue.amount);
    WriteLine("==========================================================");
  2. To execute the application, on the main menu, click Debug -> Start Without Debugging
  3. When requested, type the values as follows and press Enter after each:
    Periods:            2
    Type of Road:       1
    Posted Speed Limit: 55
    Driving Speed:      85
    Type of Issue:      3
    Type of Violation:  3
    ---------------------------
    Traffic System System
    ==========================================================
    Periods
    1 - Monday-Friday - Night (7PM - 6AM)
    2 - Monday-Friday - Morning Rush Hour (6AM - 9AM)
    3 - Monday-Friday - Regular Time (9AM - 3PM)
    4 - Monday-Friday - Afternoon Rush Hour (3PM - 7PM)
    5 - Weekend (Saturday-Sunday) and Holidays
    ----------------------------------------------------------
    Period of the infraction (1-5): 2
    ==========================================================
    Type of Road
    1 - Interstate (Ex. I95)
    2 - Federal/State Highway (Ex. US50)
    3 - State Road (Ex. TN22, MD410)
    4 - County/Local Road (Ex. Randolph Rd, Eusebio Ave, Abena Blvd) or Local - Unknown (Ex. Sterling Str, Garvey Court)
    ----------------------------------------------------------
    Type of road (1-4):             1
    ==========================================================
    Posted Speed Limit:             55
    Driving Speed:                  85
    ==========================================================
    Types of issues
    0 - No particular issues
    1 - Health issues
    2 - Driving while sleeping
    3 - Driving while using an electronic device
    4 - Driving under the influence (of alcohol, drugs, intoxicating products, etc)
    Type of issue (0-4):            3
    ==========================================================
    Type of Traffic Violation
    1 - Slow Driving
    2 - Fast Driving
    3 - Aggressive Driving
    4 - Unknown - Other
    ----------------------------------------------------------
    Type of violaction (1-4):      3
    ==========================================================
    Traffic Ticket Summary
    ----------------------------------------------------------
    Period of the day:  Monday-Friday - Morning Rush Hour (6AM - 9AM)
    Road Type:          Interstate
    Posted Speed Limit: 55
    Driving Speed:      85
    Type of Issue:      Driving while using an electronic device
         Base Ticket:   100
    Violation Type:     Aggressive Driving
         Addition Fee:  125
    ----------------------------------------------------------
    Ticket Amount:      225
    ==========================================================
  4. A Conditional Statement for a Case

    Consider and change: https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/tutorials/pattern-matching
    
    rivate enum TimeBand
    {
        MorningRush,
        Daytime,
        EveningRush,
        Overnight
    }
    
    private static TimeBand GetTimeBand(DateTime timeOfToll) =>
        timeOfToll.Hour switch
        {
            < 6 or > 19 => TimeBand.Overnight,
            < 10 => TimeBand.MorningRush,
            < 16 => TimeBand.Daytime,
            _ => TimeBand.EveningRush,
        };
        
    ---------------------------
    https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/switch-expression#case-guards
    WHEN: https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/tutorials/pattern-matching

    Previous Copyright © 2001-2022, C# Key Saturday 13 November 2021 Next