Fundamentals of Collections

Introduction

A collection, sometimes referred to as a list, is a group of items. The items can be numbers, characters, strings, or objects. In fact, a collection can be a list of other lists. In computer systems and application development, a collection is extremely helpful because it allows you to treat many values or objects as one unit, instead of always treating each individually. This ability makes many operations possible in areas of databases, communication (streaming), file processing (including storage), etc.

Practical LearningPractical Learning: Introducing Collections

  1. Start Microsoft Visual Studio
  2. Create a Console App project named PayrollPreparation1 and that supports .NET 8.0 (Long-Term Support)
  3. In the Solution Explorer, right-click PayrollPreparation1 -> New -> Folder
  4. Type Models as the name of the folder
  5. To create another class, in the Solution Explorer, right-click Models -> Add -> Class...
  6. Type Employee as the name of the class
  7. Click Add
  8. Change the document as follows:
    namespace PayrollPreparation1.Models
    {
        internal class Employee
        {
            internal int     EmployeeNumber { get; set; }
            internal string? FirstName      { get; set; }
            internal string? LastName       { get; set; }
            internal double  HourlySalary   { get; set; }
        }
    }
  9. To create another class, in the Solution Explorer, right-click Models -> Add -> Class...
  10. Type TimeSheet as the name of the class
  11. Click Add
  12. Change the document as follows:
    namespace PayrollPreparation1.Models
    {
        internal class TimeSheet
        {
            internal int     TimeSheetNumber { get; set; }
            internal int     EmployeeNumber  { get; set; }
            internal string? StartDate       { get; set; }
            internal string? EndDate         { get; set; }
            internal double  Week1Monday     { get; set; }
            internal double  Week1Tuesday    { get; set; }
            internal double  Week1Wednesday  { get; set; }
            internal double  Week1Thursday   { get; set; }
            internal double  Week1Friday     { get; set; }
            internal double  Week2Monday     { get; set; }
            internal double  Week2Tuesday    { get; set; }
            internal double  Week2Wednesday  { get; set; }
            internal double  Week2Thursday   { get; set; }
            internal double  Week2Friday     { get; set; }
    
            private double GetSalary()
            {
                double   salary = 0;
                Employee staff  = Repository.Identify(EmployeeNumber);
    
                if (staff is not null)
                {
                    salary = staff.HourlySalary;
                }
    
                return salary;
            }
    
            internal double Week1TimeWorked
            {
                get
                {
                    return Week1Monday + Week1Tuesday + Week1Wednesday + Week1Thursday + Week1Friday;
                }
            }
    
            internal (double RegularTime, double RegularPay, double Overtime, double OvertimePay) Week1PaySummary
            {
                get
                {
                    double sal      = GetSalary();
                    double regTime  = Week1TimeWorked;
                    double regPay   = sal * Week1TimeWorked;
                    double overtime = 0.00;
                    double overPay  = 0.00;
    
                    if (Week1TimeWorked is > 40.00)
                    {
                        regTime    = 40.00;
                        regPay      = sal * 40.00;
                        overtime    = Week1TimeWorked - 40.00;
                        overPay     = sal * 1.50 * overtime;
                    }
    
                    return (regTime, regPay, overtime, overPay);
                }
            }
    
            internal double Week1GrossPay
            {
                get
                {
                    (_, double regPay, _, double overPay) = Week1PaySummary;
    
                    return regPay + overPay;
                }
            }
    
            internal double Week2TimeWorked
            {
                get
                {
                    return Week2Monday + Week2Tuesday + Week2Wednesday + Week2Thursday + Week2Friday;
                }
            }
    
            internal (double RegularTime, double RegularPay,
                      double Overtime,    double OvertimePay) Week2PaySummary
            {
                get
                {
                    double sal      = GetSalary();
                    double regTime  = Week2TimeWorked;
                    double regPay   = sal * Week2TimeWorked;
                    double overtime = 0.00;
                    double overPay  = 0.00;
    
                    if (Week2TimeWorked is > 40.00)
                    {
                        regTime     = 40.00;
                        regPay      = sal * 40.00;
                        overtime    = Week2TimeWorked - 40.00;
                        overPay     = sal * 1.50 * overtime;
                    }
    
                    return (regTime, regPay, overtime, overPay);
                }
            }
    
            internal double Week2GrossPay
            {
                get
                {
                    (_, double regPay, _, double overPay) = Week2PaySummary;
    
                    return regPay + overPay;
                }
            }
    
            internal double GrossPay
            {
                get
                {
                    return Week1GrossPay + Week2GrossPay;
                }
            }
        }
    }

A Collection from an Array

The C# language by itself doesn't have a library for collections. The type of collection you can create in C# is an array, which is a type of collection but with some fundamental limitations (that can be overcome). Therefore, to start a simple collection in C#, you can create an array as we have seen in previous lessons. Here is an example:

int[] numbers = { 15, 928, 731_495, 80, 749};

In the same way, we have seen that you can create an array of objects.

Visual Basic to the Rescue

Introduction

When you create an array, the compiler requires that you let it know the number of items your array will have. This means that an array is a fixed collection of items. After creating an array, you cannot add more items than you had originally indicated (the .NET Framework, not the C# language, provides the ability, or rather a technique, or a mechanism, to grow an array). This is not an anomaly. This is the way arrays are defined in C-based languages (C++, Java, and C#). In some scenarios or applications, you want a collection that can grow and srink at will (the .NET Framework provides all types of classes to create and manage any type of collection).

One of the ways you can create a collection is to borrow it from the Visual Basic language. Before doing that, you must "import" the Visual Basic library into your application.

Practical LearningPractical Learning: Importing the Visual Basic Library

  1. In the Solution Explorer, right-click the PayrollPreparation8 project and click Manage NuGet Packages...
  2. In the NuGet: PayrollPreparation8 tab, click Browse
  3. Click in the combo box below Browse and type VisualBasic
  4. In the list, click Microsoft.VisualBasic:

    NuGet Package Management

  5. Click Install
  6. On the Preview Changes dialog box, click Apply:

    Preview Changes

Starting a Collection

To support collections, the Visual Basic language provides a class named Collection. After importing the Visual Basic library into your project, you can start by declaring a VisualBasic.Collection variable. Normally, if you are working in Microsoft Visual Studio and you have imported the Visual Basic library, as soon as you type Collection and press Enter or you press the Space bar, the studio will automatically add the Visual Basic namespace in the top section of your document. Otherwise, you can add that namespace manually or you will have to qualify every instance of Collection in your document. Here is an example:

using Microsoft.VisualBasic;

Collection numbers;

Creating a Collection from a List

If you have a list of items you want to create as a group of items, put the items between an opening square bracket ([) and a closing square bracket (]), separate the items with comas, and assign that list of the VisualBasic.Collection variable. You must end the statement with the traditional semicolon. Here is an example that creates a collection of integers:

using Microsoft.VisualBasic;

Collection numbers = [ 15, 928, 731_495, 80, 749 ];

In the same way, you can create a simple collection of strings. Here is an example:

using Microsoft.VisualBasic;

Console.WriteLine("Hello, World!");

Collection distributions = [ "Linux Mint", "openSUSE", "Arch Linux", "Ubuntu", "FreeBSD" ];

You can also use this technique to create a collection of objects. To do that, in the above placeholders where we were putting simple values, you can define the desired object. Remember to separate them with comas. Here is an example of a collection of objects:

using Microsoft.VisualBasic;
using static System.Console;

Collection states =
    [
        new State() { Abbreviation = "WA",  StateName = "Western Australia", AreaSqrKms = 2529875, Capital = "Perth"     },
        new State() { Abbreviation = "SA",  StateName = "South Australia",   AreaSqrKms =  983482, Capital = "Adelaide"  },
        new State() { Abbreviation = "QLD", StateName = "Queensland",        AreaSqrKms = 1730648, Capital = "Brisbane"  },
        new State() { Abbreviation = "NSW", StateName = "New South Wales",   AreaSqrKms =  800642, Capital = "Sydney"    },
        new State() { Abbreviation = "VIC", StateName = "Victoria",          AreaSqrKms =  227416, Capital = "Melbourne" },
        new State() { Abbreviation = "TAS", StateName = "Tasmania",          AreaSqrKms =   68401, Capital = "Hobart"    }
    ];

internal interface IAbbreviated
{
    string? Abbreviation { get; set; }
}
public abstract class GovernmentEntity
{
    public virtual string? StateName { get; set; }
    public virtual int AreaSqrKms { get; set; }
    public virtual string? Capital { get; set; }
}
public class State : GovernmentEntity,
                        IAbbreviated
{
    public string? Abbreviation { get; set; }
}

Adding an Item to a Collection

The most fundamental operation to perform on a collection is to add an item to it. To support this operation, the VisualBasic.Collection class provides a method named Add. Its syntax is:

public void Add(object? Item,
                string? Key    = default,
                object? Before = default,
                object? After  = default);

This method takes four arguments but only one is required. The required argument is the value or object to add to the VisualBasic.Collection collection. Since the argument is an object object, it can be anything, such as a number. Just like you can add one value or object, you can keep calling the VisualBasic.Collection.Add() method to add values one after another. Here are examples:

using Microsoft.VisualBasic;

Collection numbers = new Collection();

numbers.Add(15);
numbers.Add(928);
numbers.Add(731_495);
numbers.Add(80);
numbers.Add(749);

One of the advantages of a collection over an array is that, at any time, you can add a new item to a collection. To do that, simply call the VisualBasic.Collection.Add() method and pass the desired new item.

Adding a Collection of Items

If you decide to use the VisualBasic.Collection.Add() method to add items, if you have many items to add, remember that you have to call that method each time. If you already know the items to add, after the new() or the new class-name() expression, type the opening curly bracket and closing curly bracket. In those brackets, create a list of the items. Separate them with comas. Of course, you must end the statement with a semicolon. Here is an example:

using Microsoft.VisualBasic;

Collection numbers = new Collection() { 15, 928, 731_495, 80, 749 };

Adding a List to a List

Remember that the item to add to a VisualBasic.Collection collection is an object. As a result, the item can be a list to add to the list. Here are examples:

using Microsoft.VisualBasic;

Collection odds = [1, 3, 5, 7, 9 ];
Collection evens = [2, 4, 6, 8];

Collection numbers = new Collection();

numbers.Add(0);
numbers.Add(odds);
numbers.Add(58_280);
numbers.Add(evens);
numbers.Add(10);

Maintaining the Items of a Collection

Introduction

Data maintenance consists a locating records, editing, and deleting them. To assist you with such operations, the C# language provides some techniques, but most collection classes provide their own tools through methods.

The Number of Items in a Collection

One of the most valuable characteristics of a list is the number of items it has. To provide this information, the VisualBasic.Collection class is equipped with a read-only property named Count:

public int Count { get; }

The VisualBasic.Collection.Count is an integer that represents the position of an item in the list. Once you have that item, you can perform various types of operations.

Accessing the Items of a Collection

After adding items to a collection, the second most important operation to perform is to maintain those items. The operations that involve data maintenance start from locating an item. To assist you with this operation, the VisualBasic.Collection class is equipped an overloaded indexed property. Once of the versions takes an integer. Its syntax is:

public object? this[int Index] { get; }

With this property, you can use a loop (for, while, or do...while). Apply the square brackets to the name of the collection, and pass the desired index to the square brackets. Here is an example:

using Microsoft.VisualBasic;
using static System.Console;

Collection numbers = new Collection() { 15, 928, 731_495, 80, 749 };

WriteLine("Numbers");
WriteLine("----------------");

int i = 1;

// Loop
while(i <= numbers.Count)
{
    WriteLine("Number: {0}", numbers[i]);
    ++i;
}

WriteLine("================");

This would produce:

Numbers
----------------
Number: 15
Number: 928
Number: 731495
Number: 80
Number: 749
================

Press any key to close this window . . .

The VisualBasic.Collection class provides one more version of its indexed property:

public object? this[object Index] { get; }

Checking Whether a Collection Contains a Certain Item

One of the most routine operations to perform on a list is to locate an item. Many techniques are available. You can create a function to perform that operation. Here is an example:

using Microsoft.VisualBasic;
using static System.Console;

_ = Analyze();

int Analyze()
{
    Collection counties = new Collection()
    {
        "Bristol",
        "Kent",
        "Newport",
        "Providence",
        "Washington"
    };

    Write("Enter the name of a county in Rhode Island: ");
    string strCounty = ReadLine()!;

    WriteLine("----------------------------------------------------");

    if (Contains(counties, strCounty) == true)
    {
        WriteLine("\"{0}\" is one of the counties in Rhode Island.", strCounty);
    }
    else
    {
        WriteLine("There is no county named \"{0}\" in Rhode Island.", strCounty);
    }

    WriteLine("====================================================");

    return 1_000;
}

bool Contains(Collection coll, object item)
{
    int i = 1;

    while (i <= coll.Count)
    {
        if (coll[i]!.ToString()!.Equals(item) )
        {
            return true;
        }

        ++i;
    }

    return false;
}

Here is an example of running the application:

nter the name of a county in Rhode Island: Newport
----------------------------------------------------
"Newport" is one of the counties in Rhode Island.
====================================================

Press any key to close this window . . .

Here is another example of running the application:

Enter the name of a county in Rhode Island: News Port
----------------------------------------------------
There is no county named "News Port" in Rhode Island.
====================================================

Press any key to close this window . . .

Iterating Through a Collection

As a normal list layout, the VisualBasic.Collection class is equipped with a method named GetEnumerator. Its syntax is:

public System.Collections.IEnumerator GetEnumerator ();

This method returns an IEnumerator object. As a result, this method makes it possible to use a foreach loop to visit each item of a list. Here is an example of doing that:

using Microsoft.VisualBasic;
using static System.Console;

Collection months = new()
{
    "January", "February", "March",
    "April",   "May",      "June",
    "July",    "August",   "September",
    "October", "November", "December", 
};

WriteLine("Calendar");
WriteLine("-------------------");

foreach (var month in months)
{
    WriteLine("Month: {0}", month);
}

WriteLine("===================");

This produce:

Calendar
-------------------
Month:  January
Month:  February
Month:  March
Month:  April
Month:  May
Month:  June
Month:  July
Month:  August
Month:  September
Month:  October
Month:  November
Month:  December
===================

Press any key to close this window . . .

We saw that, since the VisualBasic.Collection.Add() method takes an object object, you can pass a list to it as argument. If you do, you can use a foreach loop to visit each item of the list passed as argument. Here is an example:

using Microsoft.VisualBasic;
using static System.Console;

Collection odds  = [1, 3, 5, 7, 9];
Collection evens = [2, 4, 6, 8];

Collection numbers = new Collection();

numbers.Add(0);
numbers.Add(odds);
numbers.Add(58_280);
numbers.Add(evens);
numbers.Add(10);

WriteLine("Numbers");
WriteLine("---------------");

foreach (var item in numbers)
{
    if (item is Collection colls)
    {
        foreach (var coll in colls)
        {
            WriteLine("Number: {0}", coll);
        }
    }
    else
    {
        WriteLine("Number: {0}", item);
    }
}

WriteLine("===============");

This would produce:

Numbers
---------------
Number: 0
Number: 1
Number: 3
Number: 5
Number: 7
Number: 9
Number: 58280
Number: 2
Number: 4
Number: 6
Number: 8
Number: 10
===============

Press any key to close this window . . .

Deleting Items from a Collection

Removing an Item from a List

The final common operation to perform on a list consists of deleting an item. To assist you with this operation, the VisualBasic.Collection class is equipped with an oveloaded method named Remove.

To let you delete an item based on its position, the VisualBasic.Collection class provides the following version of its Remove() method:

public void Remove (int Index);

When calling this method, pass a natural number that represents the index of the item you want to remove. Here is an example:

using Microsoft.VisualBasic;
using static System.Console;

Collection months = new()
{
    "January",
    "February",
    "March",
    "April",
    "May",
    "June",
    "July",
    "August",
    "September",
    "October",
    "November",
    "December",
};

WriteLine("Calendar");
WriteLine("-------------------");

foreach (var month in months)
{
    WriteLine("Month: {0}", month);
}
WriteLine("===================");

months.Remove(4);

WriteLine("-------------------");

foreach (var month in months)
{
    WriteLine("Month: {0}", month);
}

WriteLine("===================");

This would produce:

Calendar
-------------------
Month: January
Month: February
Month: March
Month: April
Month: May
Month: June
Month: July
Month: August
Month: September
Month: October
Month: November
Month: December
===================
-------------------
Month: January
Month: February
Month: March
Month: May
Month: June
Month: July
Month: August
Month: September
Month: October
Month: November
Month: December
===================

Press any key to close this window . . .

When calling the VisualBasic.Collection.Remove() method, if you pass 0, a negative number, or a number that is higher than the VisualBasic.Collection.Count value of the collection, the compiler would throw an System.IndexOutOfRangeException exception. Of course, if you are anticipating this type of situation, you can create a conditional statement. This can be done as follows:

using Microsoft.VisualBasic;
using static System.Console;

int index = -4;

Collection months = new()
{
    "January", "February", "March",
    "April",   "May",      "June",
    "July",    "August",   "September",
    "October", "November", "December",
};

if ((index is <= 0) | (index is > 12))
{
    WriteLine("You must provide a valid index for the item you want to remove.");
}
else
{
    months.Remove(index);

    WriteLine("Calendar");
    WriteLine("-------------------");

    foreach (var month in months)
    {
        WriteLine("Month: {0}", month);
    }

    WriteLine("===================");
}

Clearing a Collection

Consider the following code:

using Microsoft.VisualBasic;
using static System.Console;

Collection counties = new Collection()
{
    "Bristol",
    "Kent",
    "Newport",
    "Providence",
    "Washington"
};

int i = 1;

WriteLine("Rhode Island");
WriteLine("------------------");

while (i <= counties.Count)
{
    WriteLine("County: {0}", counties[i]);
    
    ++i;
}
WriteLine("==================");

This would produce:

Rhode Island
------------------
County: Bristol
County: Kent
County: Newport
County: Providence
County: Washington
==================

Press any key to close this window . . .

Clearing a colection consissts of deleting all its items, as opposed to removing one item at a time. To assist you with this operation, the VisualBasic.Collection class provides a method named Clear. Its syntax is:

public void Clear();

To remove all the items from a list, you can simply call this method on the VisualBasic.Collection variable. This can be done as follows:

using Microsoft.VisualBasic;
using static System.Console;

Collection counties = new Collection()
{
    "Bristol",
    "Kent",
    "Newport",
    "Providence",
    "Washington"
};

counties.Clear();

int i = 1;

WriteLine("Rhode Island");
WriteLine("------------------");

while (i <= counties.Count)
{
    WriteLine("County: {0}", counties[i]);
    
    ++i;
}
WriteLine("==================");

When calling the VisualBasic.Collection.Clear() method, if the collection is empty, nothing would happen. If the collection contains at least one item, it would be emptied. The above code would produce:

Rhode Island
------------------
==================

Press any key to close this window . . .

An Empty Collection

A collection is referred to as empty if it doesn't contain any item. You have various options to get en empty collection.

As the simplest way to have an empty collection, you can declare a VisualBasic.Collection variable and initialize it with its default constructor. This can be done as follows:

using Microsoft.VisualBasic;

Collection months = new();

When a collection is empty, its Count property is equal to 0.

After declaring a simple VisualBasic.Collection variable, if you want to populate it, you can call or keep calling, the Add() method to add items to the list.

We already saw how to delete some items from a collection. In the same way, you can keep calling the VisualBasic.Collection.Remove() method to remove more items. If the last item is deleted, the list becomes empty. That's another way to get an empty list.

If you call the VisualBasic.Collection.Clear() method to delete all items from a list, the list becomes empty. That's one more way to get an empty list.

ApplicationPractical Learning: Creating and Using a Collection

  1. To create a class, in the Solution Explorer, right-click Models -> Add -> Class...
  2. Type Repository as the name of the class
  3. Click Add
  4. Change the document as follows:
    using Microsoft.VisualBasic;
    
    namespace PayrollPreparation1.Models
    {
        internal class Repository
        {
            internal static Collection HireEmployees()
            {        
                Collection members =
                    [
                        new Employee()
                        {
                            EmployeeNumber = 370_595,
                            FirstName      = "Michael",
                            LastName       = "Carlock",
                            HourlySalary   = 28.25
                        },
                        
                        new Employee()
                        {
                            EmployeeNumber = 826_384,
                            FirstName      = "Catherine",
                            LastName       = "Busbey",
                            HourlySalary   = 64.37
                        },
                        
                        new Employee()
                        {
                            EmployeeNumber = 293_759,
                            FirstName      = "Anthony",
                            LastName       = "Ewel",
                            HourlySalary   = 82.68
                        },
                        
                        new Employee()
                        {
                            EmployeeNumber = 175_004,
                            FirstName      = "Andrew",
                            LastName       = "Sanders",
                            HourlySalary   = 26.97
                        },
                        
                        new Employee()
                        {
                            EmployeeNumber = 697_415,
                            FirstName      = "Jennifer",
                            LastName       = "Simms",
                            HourlySalary   = 31.57
                        },
                        
                        new Employee()
                        {
                            EmployeeNumber = 220_840,
                            FirstName      = "Raymond",
                            LastName       = "Dobbs",
                            HourlySalary   = 95.77
                        }
                    ];
    
                return members;
            }
    
            internal static Collection GetTimesWorked()
            {
                Collection times = new Collection();
    
                times.Add(new TimeSheet()
                {
                    TimeSheetNumber = 100_000,
                    StartDate       = "01-Jan-2024",
                    EndDate         = "14-Jan-2024",
                    EmployeeNumber  = 370_595,
                    Week1Monday     = 7,
                    Week1Tuesday    = 8,
                    Week1Wednesday  = 6.5,
                    Week1Thursday   = 8.5,
                    Week1Friday     = 6.5,
                    Week2Monday     = 8,
                    Week2Tuesday    = 7.5,
                    Week2Wednesday  = 8.5,
                    Week2Thursday   = 8,
                    Week2Friday     = 7.5
                });
                times.Add(new TimeSheet()
                {
                    TimeSheetNumber = 205_000,
                    StartDate       = "01-Jan-2024",
                    EndDate         = "14-Jan-2024",
                    EmployeeNumber  = 826_384,
                    Week1Monday     = 9.5,
                    Week1Tuesday    = 8,
                    Week1Wednesday  = 10.5,
                    Week1Thursday   = 9,
                    Week1Friday     = 8.5,
                    Week2Monday     = 8.5,
                    Week2Tuesday    = 10,
                    Week2Wednesday  = 9,
                    Week2Thursday   = 10.5,
                    Week2Friday     = 9.5
                });
                times.Add(new TimeSheet()
                {
                    TimeSheetNumber = 442_000,
                    StartDate       = "01-Jan-2024",
                    EndDate         = "14-Jan-2024",
                    EmployeeNumber  = 220_840,
                    Week1Monday     = 9,
                    Week1Tuesday    = 8.5,
                    Week1Wednesday  = 10,
                    Week1Thursday   = 9.5,
                    Week1Friday     = 8,
                    Week2Monday     = 10.5,
                    Week2Tuesday    = 10,
                    Week2Wednesday  = 9.5,
                    Week2Thursday   = 10,
                    Week2Friday     = 8.5
                });
                times.Add(new TimeSheet()
                {
                    TimeSheetNumber = 505_500,
                    StartDate       = "01-Jan-2024",
                    EndDate         = "14-Jan-2024",
                    EmployeeNumber  = 175_004,
                    Week1Monday     = 9,
                    Week1Tuesday    = 10.5,
                    Week1Wednesday  = 7,
                    Week1Thursday   = 9.5,
                    Week1Friday     = 8.5,
                    Week2Monday     = 10,
                    Week2Tuesday    = 8.5,
                    Week2Wednesday  = 9.5,
                    Week2Thursday   = 8.5,
                    Week2Friday     = 10.5
                });
                times.Add(new TimeSheet()
                {
                    TimeSheetNumber = 101_505,
                    StartDate       = "01-Jan-2024",
                    EndDate         = "14-Jan-2024",
                    EmployeeNumber  = 293_759,
                    Week1Monday     = 10.5,
                    Week1Tuesday    = 9,
                    Week1Wednesday  = 10.5,
                    Week1Thursday   = 8,
                    Week1Friday     = 9.5,
                    Week2Monday     = 9.5,
                    Week2Tuesday    = 10.5,
                    Week2Wednesday  = 9,
                    Week2Thursday   = 8.5,
                    Week2Friday     = 10.5
                });
                times.Add(new TimeSheet()
                {
                    TimeSheetNumber = 202_240,
                    StartDate       = "01-Jan-2024",
                    EndDate         = "14-Jan-2024",
                    EmployeeNumber  = 697_415,
                    Week1Monday     = 8,
                    Week1Tuesday    = 8,
                    Week1Wednesday  = 8,
                    Week1Thursday   = 8,
                    Week1Friday     = 8,
                    Week2Monday     = 8,
                    Week2Tuesday    = 8,
                    Week2Wednesday  = 8,
                    Week2Thursday   = 8,
                    Week2Friday     = 8
                });
    
                times.Add(new TimeSheet()
                {
                    TimeSheetNumber = 442_200,
                    StartDate       = "15-Jan-2024",
                    EndDate         = "14-Jan-2024",
                    EmployeeNumber  = 220_840,
                    Week1Monday     = 12,
                    Week1Tuesday    = 10.5,
                    Week1Wednesday  = 12.50,
                    Week1Thursday   = 10.5,
                    Week1Friday     = 12.5,
                    Week2Monday     = 12.5,
                    Week2Tuesday    = 14,
                    Week2Wednesday  = 11.5,
                    Week2Thursday   = 12,
                    Week2Friday     = 12.5
                });
                times.Add(new TimeSheet()
                {
                    TimeSheetNumber = 100_010,
                    StartDate       = "15-Jan-2024",
                    EndDate         = "28-Jan-2024",
                    EmployeeNumber  = 370_595,
                    Week1Monday     = 9,
                    Week1Tuesday    = 6.5,
                    Week1Wednesday  = 7,
                    Week1Thursday   = 9.5,
                    Week1Friday     = 10.5,
                    Week2Monday     = 8,
                    Week2Tuesday    = 9.5,
                    Week2Wednesday  = 8,
                    Week2Thursday   = 10,
                    Week2Friday     = 6.5
                });
                times.Add(new TimeSheet()
                {
                    TimeSheetNumber = 205_050,
                    StartDate       = "15-Jan-2024",
                    EndDate         = "28-Jan-2024",
                    EmployeeNumber  = 826_384,
                    Week1Monday     = 10.5,
                    Week1Tuesday    = 8.5,
                    Week1Wednesday  = 9.5,
                    Week1Thursday   = 10.5,
                    Week1Friday     = 10.5,
                    Week2Monday     = 8.5,
                    Week2Tuesday    = 10.5,
                    Week2Wednesday  = 9,
                    Week2Thursday   = 8.5,
                    Week2Friday     = 10.5
                });
                times.Add(new TimeSheet()
                {
                    TimeSheetNumber = 505_550,
                    StartDate       = "14-Jan-2024",
                    EndDate         = "28-Jan-2024",
                    EmployeeNumber  = 175_004,
                    Week1Monday     = 7.5,
                    Week1Tuesday    = 8,
                    Week1Wednesday  = 7.5,
                    Week1Thursday   = 6.5,
                    Week1Friday     = 6.5,
                    Week2Monday     = 10.5,
                    Week2Tuesday    = 9.5,
                    Week2Wednesday  = 10.5,
                    Week2Thursday   = 8,
                    Week2Friday     = 10
                });
                times.Add(new TimeSheet()
                {
                    TimeSheetNumber = 101_505,
                    StartDate       = "15-Jan-2024",
                    EndDate         = "28-Jan-2024",
                    EmployeeNumber  = 293_759,
                    Week1Monday     = 10,
                    Week1Tuesday    = 10.5,
                    Week1Wednesday  = 12.5,
                    Week1Thursday   = 10,
                    Week1Friday     = 11.5,
                    Week2Monday     = 12.5,
                    Week2Tuesday    = 14,
                    Week2Wednesday  = 10,
                    Week2Thursday   = 12.5,
                    Week2Friday     = 10
                });
                times.Add(new TimeSheet()
                {
                    TimeSheetNumber = 202_240,
                    StartDate       = "15-Jan-2024",
                    EndDate         = "28-Jan-2024",
                    EmployeeNumber  = 697_415,
                    Week1Monday     = 9,
                    Week1Tuesday    = 9,
                    Week1Wednesday  = 9,
                    Week1Thursday   = 9,
                    Week1Friday     = 9,
                    Week2Monday     = 9,
                    Week2Tuesday    = 9,
                    Week2Wednesday  = 9,
                    Week2Thursday   = 9,
                    Week2Friday     = 9
                });
    
                return times;
            }
    
            internal static Employee Identify(in int number)
            {
                Employee employee    = new();
                Collection employees = HireEmployees();
    
                foreach (Employee emp in employees)
                {
                    if (emp.EmployeeNumber == number)
                    {
                        employee = emp;
                        break;
                    }
                }
    
                return employee;
            }
    
            internal static TimeSheet GetTimeWorked(in int number)
            {
                TimeSheet time    = new();
                Collection sheets = GetTimesWorked();
    
                foreach (TimeSheet ts in sheets)
                {
                    if (ts.TimeSheetNumber == number)
                    {
                        time = ts;
                        break;
                    }
                }
    
                return time;
            }
    
            internal static double CalculateTaxAmount(in double salary)
            {
                double taxAmount = 0;
    
                if ((salary >= 0.00) && (salary <= 1_207))
                {
                    taxAmount = 0.00;
                }
                else if ((salary > 1_207) && (salary <= 2_414))
                {
                    taxAmount = salary * 2.00 / 100.00;
                }
                else if ((salary > 2_414) && (salary <= 3_621))
                {
                    taxAmount = 24.00 + ((salary - 2_414) * 2.50 / 100.00);
                }
                else if ((salary > 3_621) && (salary <= 4_828))
                {
                    taxAmount = 54.00 + ((salary - 3_621) * 3.00 / 100.00);
                }
                else if ((salary > 4_828) && (salary <= 6_035))
                {
                    taxAmount = 90.00 + ((salary - 4_828) * 3.50 / 100.00);
                }
                else if ((salary >= 6_035) && (salary < 7_242))
                {
                    taxAmount = 132.00 + ((salary - 6_035) * 4.00 / 100.00);
                }
                else if ((salary >= 7_242) && (salary < 8_449))
                {
                    taxAmount = 180.00 + ((salary - 7_242) * 4.50 / 100.00);
                }
                else // if(grossSalary >= 8_449)
                {
                    taxAmount = 234.00 + ((salary - 8_449) * 4.95 / 100.00);
                }
    
                return taxAmount;
            }
    
            internal static double CalculateNetPay(in double income, in double taxAmt)
            {
                return income - taxAmt;
            }
        }
    }
  5. In the Solution Explorer, right-click Program.cs -> Rename
  6. Type PayrollProcessing (to get PayrollProcessing.cs) and press Enter
  7. Click the PayrollProcessing.cs tab and change its document as follows:
    using static System.Console;
    using PayrollPreparation1.Models;
    
    int nbr = 0;
        
    GetTimeSheetNumber(ref nbr);
    PreparePayroll(in nbr);
    
    int GetTimeSheetNumber(ref int nbr)
    {
        nbr = 0;
    
        try
        {
            Write("Enter the time sheet number: ");
            nbr = int.Parse(ReadLine()!);
        }
        catch(FormatException fex)
        {
            WriteLine("You might have entered a bad value for the time sheet number.");
            WriteLine("The application produced the following error: " + fex.Message);
        }
    
        return nbr;
    }
    void PreparePayroll(in int number)
    {
        if(number == 0)
        {
            WriteLine("There is no valid time sheet number");
            return;
        }
    
        TimeSheet timeSheet = Repository.GetTimeWorked(nbr);
        Employee staff = Repository.Identify(timeSheet.EmployeeNumber);
    
        WriteLine("===========================================================");
        WriteLine("FUN DEPARTMENT STORE");
        WriteLine("===========================================================");
        WriteLine("Payroll Evaluation");
        WriteLine("===========================================================");
        WriteLine("Employee Information");
        WriteLine("-----------------------------------------------------------");
        WriteLine("Employee #:               {0}", staff.EmployeeNumber);
        WriteLine($"Full Name:                {staff.FirstName} {staff.LastName}");
        WriteLine($"Hourly Salary:            {staff.HourlySalary:f}");
        WriteLine("===========================================================");
        WriteLine("Time Sheet Summary");
        WriteLine("-----------------------------------------------------------");
        WriteLine("Time Sheet #:             {0}", timeSheet.TimeSheetNumber);
        WriteLine("-----------------------------------------------------------");
        WriteLine($"Time Sheet Start Date:    {timeSheet.StartDate:f}");
        WriteLine($"Time Sheet End Date:      {timeSheet.EndDate:f}");
        WriteLine("===========================================================");
        WriteLine("Time Worked");
        WriteLine("-------+--------+---------+-----------+----------+---------");
        WriteLine("       | Monday | Tuesday | Wednesday | Thursday | Friday");
        WriteLine("-------+--------+---------+-----------+----------+---------");
        Write($"Week 1 |{timeSheet.Week1Monday,6:f}  |  ");
        Write($"{timeSheet.Week1Tuesday,5:f}  |   ");
        Write($"{timeSheet.Week1Wednesday,5:f}   |  ");
        Write($"{timeSheet.Week1Thursday,5:f}   |  ");
        WriteLine($"{timeSheet.Week1Friday,5:f}");
        WriteLine("-------+--------+---------+-----------+----------+---------");
        Write($"Week 2 |{timeSheet.Week2Monday,6:f}  |  ");
        Write($"{timeSheet.Week2Tuesday,5:f}  |   ");
        Write($"{timeSheet.Week2Wednesday,5:f}   |  ");
        Write($"{timeSheet.Week2Thursday,5:f}   |  ");
        WriteLine($"{timeSheet.Week2Friday,5:f}");
        WriteLine("=======+========+=========+===========+==========+=========");
        WriteLine("                                    Pay Summary");
        WriteLine("-----------------------------------------------------------");
        WriteLine("                                  Time     Pay");
        WriteLine("-----------------------------------------------------------");
        Write($"                     Regular:     {(timeSheet.Week1PaySummary.RegularTime + timeSheet.Week2PaySummary.RegularTime),5:f}   ");
        WriteLine($"{(timeSheet.Week1PaySummary.RegularPay + timeSheet.Week2PaySummary.RegularPay):f}");
        WriteLine("-----------------------------------------------------------");
        Write($"                     Overtime:    {(timeSheet.Week1PaySummary.Overtime + timeSheet.Week2PaySummary.Overtime),5:f}  ");
        WriteLine($"{(timeSheet.Week1PaySummary.OvertimePay + timeSheet.Week2PaySummary.OvertimePay),8:f}");
        WriteLine("===========================================================");
    
        double salary = timeSheet.GrossPay;
        double tax = Repository.CalculateTaxAmount(salary);
        double netPay = Repository.CalculateNetPay(salary, tax);
        WriteLine($"                     Gross Income:       {salary,8:f}");
        WriteLine("===========================================================");
        WriteLine("                     Tax Amount:         {0,8:f}", tax);
        WriteLine("-----------------------------------------------------------");
        WriteLine("                     Net Pay:            {0,8:f}", netPay);
        WriteLine("===========================================================");
    }
  8. To execute, on the main menu, click Debug -> Start Without Debugging
  9. When requested, type the time sheet number as 100000 and press Enter:
    Enter the time sheet number: 100000
    ===========================================================
    FUN DEPARTMENT STORE
    ===========================================================
    Payroll Evaluation
    ===========================================================
    Employee Information
    -----------------------------------------------------------
    Employee #:               370595
    Full Name:                Michael Carlock
    Hourly Salary:            28.25
    ===========================================================
    Time Sheet Summary
    -----------------------------------------------------------
    Time Sheet #:             100000
    -----------------------------------------------------------
    Time Sheet Start Date:    01-Jan-2024
    Time Sheet End Date:      14-Jan-2024
    ===========================================================
    Time Worked
    -------+--------+---------+-----------+----------+---------
           | Monday | Tuesday | Wednesday | Thursday | Friday
    -------+--------+---------+-----------+----------+---------
    Week 1 |  7.00  |   8.00  |    6.50   |   8.50   |   6.50
    -------+--------+---------+-----------+----------+---------
    Week 2 |  8.00  |   7.50  |    8.50   |   8.00   |   7.50
    =======+========+=========+===========+==========+=========
                                        Pay Summary
    -----------------------------------------------------------
                                      Time     Pay
    -----------------------------------------------------------
                         Regular:     76.00   2147.00
    -----------------------------------------------------------
                         Overtime:     0.00      0.00
    ===========================================================
                         Gross Income:        2147.00
    ===========================================================
                         Tax Amount:            42.94
    -----------------------------------------------------------
                         Net Pay:             2104.06
    ===========================================================
    
    Press any key to close this window . . .

Introduction to Dictionaries

Overview

A dictionary is a collection of items where each item is a combination of a key and a value, or a value and a key. This means that each item in fact contains two values.

Creating a Dictionary

A Visual Basic dictionary starts like any collection. This means that, to create a dictionary, start by declaring a VisualBasic.Collection variable. Then, to add an item to the dictionary, call the VisualBasic.Collection.Add() method. Remember that this method takes an object argument, which means the argument can be anything. Based on this, to add a dictionary item to the collection, pass two values (or an object and a value) to the method. The second item should be passed as a string. The first part can be anything you want, such as a number, a string, an object, etc. Here is an example of a dictionary where each item is a combination of two strings:

using Microsoft.VisualBasic;

Collection states = new Collection();

states.Add("Western Australia", "WA");
states.Add("South Australia", "SA");
states.Add("Queensland", "QLD");
states.Add("New South Wales", "NSW");
states.Add("Victoria", "VIC");
states.Add("Tasmania", "TAS");

Accessing the Items of a Dictionary

To assist you with accessing the items of a dictionary, the VisualBasic.Collection class is equipped with the following version of its indexed property:

public object? this[string Key] { get; }

Using this version of the indexed property, pass the argument as the key, which is the second argument to the Add() method. When you do that, the property produces the value or object corresponding to the key of the same item, that value or object is the one that was passed as the first part of the argument of the Add() method. Here are examples:

using Microsoft.VisualBasic;
using static System.Console;

Collection states = new();

states.Add("Western Australia", "WA");
states.Add("South Australia",   "SA");
states.Add("Queensland",        "QLD");
states.Add("New South Wales",   "NSW");
states.Add("Victoria",          "VIC");
states.Add("Tasmania",          "TAS");

WriteLine("Australia");
WriteLine("--------------------------");
WriteLine("State:  {0}", states["WA"]);
WriteLine("State:  {0}", states["SA"]);
WriteLine("State:  {0}", states["QLD"]);
WriteLine("State:  {0}", states["NSW"]);
WriteLine("State:  {0}", states["VIC"]);
WriteLine("State:  {0}", states["TAS"]);
WriteLine("==========================");

This would produce:

Australia
--------------------------
State:  Western Australia
State:  South Australia
State:  Queensland
State:  New South Wales
State:  Victoria
State:  Tasmania
==========================

Press any key to close this window . . .

An important rule of a dictionary is that each key must be unique. In your dictionary, if you create two items that have the same key, when you access the dictionary, the compiler will throw an System.ArgumentException exception. Here is an example:

using Microsoft.VisualBasic;
using static System.Console;

Collection months = new()
{
    { "January",   "Jan" },
    { "February",  "Feb" },
    { "March",     "Mar" },
    { "April",     "Apr" },
    { "May",       "May" },
    { "June",      "Jun" },
    { "July",      "Jul" },
    { "August",    "Aug" },
    { "September", "Feb" },
    { "October",   "oct" },
    { "November",  "Nov" },
    { "December",  "Dec" },
};

WriteLine("Month: {0}", months["Sep"]);

This would produce:

Unhandled exception. System.ArgumentException: Add failed. Duplicate key value supplied.
   at Microsoft.VisualBasic.Collection.Add(Object Item, String Key, Object Before, Object After)
   at Program.<Main>$(String[] args) in E:\Users\pkatts\source\repos\Consoles\Exercise1\Exercise1\Exercise.cs:line 4

Press any key to close this window . . .

Dictionary Maintenance

Iterating Through a Dictionary

Remember that the VisualBasic.Collection class is equipped with a GetEnumerator() method that returns an IEnumerator object. This allows you to use a foreach loop to visit each item of the dictionary. If you use a foreach loop on a dictionary, each section would produce the value of the item. Here is an example:

using Microsoft.VisualBasic;
using static System.Console;

Collection states = new Collection
{
    { "Western Australia", "WA" },
    { "South Australia", "SA" },
    { "Queensland", "QLD" },
    { "New South Wales", "NSW" },
    { "Victoria", "VIC" },
    { "Tasmania", "TAS" }
};

WriteLine("Australia");
WriteLine("--------------------------");

foreach(var state in states)
{
    WriteLine("State:  {0}", state);
}

WriteLine("==========================");

This would produce:

Australia
--------------------------
State:  Western Australia
State:  South Australia
State:  Queensland
State:  New South Wales
State:  Victoria
State:  Tasmania
==========================

Press any key to close this window . . .

Checking Whether a Collection Contains a Certain Item

To let you locate a value in a dictionary, the VisualBasic.Collection class is equipped with a Boolean method named Contains. Its syntax is:

public bool Contains (string Key);

This method takes one argument as the key of the item you are trying to find. The argument is passed as a string. When this method is called, the compiler will try to find an item that uses that key. If the item is found, the method returns true and you can get its value. Here is an example:

using Microsoft.VisualBasic;
using static System.Console;

Collection states = new Collection
{
    { "Western Australia", "WA" },
    { "South Australia", "SA" },
    { "Queensland", "QLD" },
    { "New South Wales", "NSW" },
    { "Victoria", "VIC" },
    { "Tasmania", "TAS" }
};

WriteLine("Australia");
WriteLine("--------------------------");

if (states.Contains("NSW") == true)
{
    WriteLine("State:  {0}", states["NSW"]);
}

WriteLine("==========================");

This would produce:

Australia
--------------------------
State:  New South Wales
==========================

Press any key to close this window . . .

Removing an Item from a Dictionary

Remember that a dictionary is a collection of key/value items. After creating a dictionary, for your maintenance operations, you may be interested in removing an item. To perform this operation, you must know the key of the item you want to delete. To assist you with this operation, the VisualBasic.Collection classs provides the following version of its Remove() method:

public void Remove (string Key);

When calling this method, pass a string that represents the key of the item you want to remove. Here is an example:

using Microsoft.VisualBasic;
using static System.Console;

Collection months = new()
{
    { "January",   "Jan" },
    { "February",  "Feb" },
    { "March",     "Mar" },
    { "April",     "Apr" },
    { "May",       "May" },
    { "June",      "Jun" },
    { "July",      "Jul" },
    { "August",    "Aug" },
    { "September", "Sep" },
    { "October",   "oct" },
    { "November",  "Nov" },
    { "December",  "Dec" },
};

months.Remove("Feb");

WriteLine("Months");
WriteLine("-------------------");

foreach (var month in months)
{
    WriteLine("Month: {0}", month);
}
WriteLine("===================");

This would produce:

Months
-------------------
Month: January
Month: March
Month: April
Month: May
Month: June
Month: July
Month: August
Month: September
Month: October
Month: November
Month: December
===================

Press any key to close this window . . .

When calling the VisualBasic.Collection.Remove(string Key) method, if you pass a key that doesn't exist in the dictionary, the compiler would throw an System.ArgumentException exception. Of course, there are actions you can take to find out whether the dictionary contains the key contains that key.

Clearing a Collection

Consider the following code:

using Microsoft.VisualBasic;
using static System.Console;

Collection months = new()
{
    { "January",   "Jan" },
    { "February",  "Feb" },
    { "March",     "Mar" },
    { "April",     "Apr" },
    { "May",       "May" },
    { "June",      "Jun" },
    { "July",      "Jul" },
    { "August",    "Aug" },
    { "September", "Sep" },
    { "October",   "oct" },
    { "November",  "Nov" },
    { "December",  "Dec" },
};

WriteLine("Months");
WriteLine("-------------------");

foreach (var month in months)
{
    WriteLine("Month: {0}", month);
}
WriteLine("===================");

WriteLine("Months");
WriteLine("-------------------");

foreach (var month in months)
{
    WriteLine("Month: {0}", month);
}
WriteLine("===================");

This would produce:

Months
-------------------
Month: January
Month: February
Month: March
Month: April
Month: May
Month: June
Month: July
Month: August
Month: September
Month: October
Month: November
Month: December
===================
Months
-------------------
Month: January
Month: February
Month: March
Month: April
Month: May
Month: June
Month: July
Month: August
Month: September
Month: October
Month: November
Month: December
===================

Press any key to close this window . . .

Clearing a collection consists of deleting all its items, as opposed to removing one item at a time. To assist you with this operation, the VisualBasic.Collection class provides a method named Clear. Its syntax is:

public void Clear();

To remove all the items of a dictionary, you can simply call this method on the VisualBasic.Collection variable. This can be done as follows:

using Microsoft.VisualBasic;
using static System.Console;

Collection months = new()
{
    { "January",   "Jan" },
    { "February",  "Feb" },
    { "March",     "Mar" },
    { "April",     "Apr" },
    { "May",       "May" },
    { "June",      "Jun" },
    { "July",      "Jul" },
    { "August",    "Aug" },
    { "September", "Sep" },
    { "October",   "oct" },
    { "November",  "Nov" },
    { "December",  "Dec" },
};

WriteLine("Months");
WriteLine("-------------------");

foreach (var month in months)
{
    WriteLine("Month: {0}", month);
}
WriteLine("===================");

months.Clear();

WriteLine("Months");
WriteLine("-------------------");

foreach (var month in months)
{
    WriteLine("Month: {0}", month);
}
WriteLine("===================");

When calling the VisualBasic.Collection.Clear() method, if the collection is empty, nothing would happen. If the collection contains at least one item, it would be emptied. The above code would produce:

Months
-------------------
Month: January
Month: February
Month: March
Month: April
Month: May
Month: June
Month: July
Month: August
Month: September
Month: October
Month: November
Month: December
===================
Months
-------------------
===================

Press any key to close this window . . .

Clearing a Collection

Consider the following code:

using Microsoft.VisualBasic;
using static System.Console;

Collection months = new()
{
    { "January",   "Jan" },
    { "February",  "Feb" },
    { "March",     "Mar" },
    { "April",     "Apr" },
    { "May",       "May" },
    { "June",      "Jun" },
    { "July",      "Jul" },
    { "August",    "Aug" },
    { "September", "Sep" },
    { "October",   "oct" },
    { "November",  "Nov" },
    { "December",  "Dec" },
};

WriteLine("Months");
WriteLine("-------------------");

foreach (var month in months)
{
    WriteLine("Month: {0}", month);
}
WriteLine("===================");

WriteLine("Months");
WriteLine("-------------------");

foreach (var month in months)
{
    WriteLine("Month: {0}", month);
}
WriteLine("===================");

This would produce:

Months
-------------------
Month: January
Month: February
Month: March
Month: April
Month: May
Month: June
Month: July
Month: August
Month: September
Month: October
Month: November
Month: December
===================
Months
-------------------
Month: January
Month: February
Month: March
Month: April
Month: May
Month: June
Month: July
Month: August
Month: September
Month: October
Month: November
Month: December
===================

Press any key to close this window . . .

To delete all items from a dictionary, you can call the VisualBasic.Collection.Clear() method. Here is an example:

using Microsoft.VisualBasic;
using static System.Console;

Collection months = new()
{
    { "January",   "Jan" },
    { "February",  "Feb" },
    { "March",     "Mar" },
    { "April",     "Apr" },
    { "May",       "May" },
    { "June",      "Jun" },
    { "July",      "Jul" },
    { "August",    "Aug" },
    { "September", "Sep" },
    { "October",   "oct" },
    { "November",  "Nov" },
    { "December",  "Dec" },
};

WriteLine("Months");
WriteLine("-------------------");

foreach (var month in months)
{
    WriteLine("Month: {0}", month);
}
WriteLine("===================");

months.Clear();

WriteLine("Months");
WriteLine("-------------------");

foreach (var month in months)
{
    WriteLine("Month: {0}", month);
}
WriteLine("===================");

Previous Copyright © 2008-2024, FunctionX Friday 26 November 2021 Next