Exercise - Throw and catch exceptions in a C# console application
In this exercise, you'll develop a try code block and catch clause in the top-level statements, create and throw exceptions in the MakeChange method, and then complete the catch code block using an exception object. You complete the following tasks during this exercise:
- Update top-level statements: Implement a
try-catchpattern in the top-level statements. Thetrycode block will contain the call toMakeChange. - Update
MakeChangemethod: Create and throw exceptions for "Insufficient till" and "Underpayment" issues. - Update the
catchcode block to use properties of the thrown exception. - Verification test: perform verification tests for the code that you develop in this exercise.
Add a try-catch pattern to the top-level statements
In this task, you'll enclose the call to the MakeChange method inside a try statement and create the corresponding catch clause.
Ensure that the Program.cs file is open in the Visual Studio Code Editor.
Locate the following code lines:
// MakeChange manages the transaction and updates the till string transactionMessage = MakeChange(itemCost, cashTill, paymentTwenties, paymentTens, paymentFives, paymentOnes); // Backup Calculation - each transaction adds current "itemCost" to the till if (transactionMessage == "transaction succeeded") { Console.WriteLine($"Transaction successfully completed."); registerCheckTillTotal += itemCost; } else { Console.WriteLine($"Transaction unsuccessful: {transactionMessage}"); }Take a minute to consider the purpose of this code.
Notice that
MakeChangereturns a string value. The return value is assigned to a variable namedtransactionMessage. IftransactionMessageis equal to "transaction succeeded", then the cost of the purchased item is added toregisterCheckTillTotal. The variableregisterCheckTillTotalis used to verify the till balance calculated by theMakeChangemethod.To enclose the call to the
MakeChangemethod in atrystatement code block, update your code as follows:try { // MakeChange manages the transaction and updates the till string transactionMessage = MakeChange(itemCost, cashTill, paymentTwenties, paymentTens, paymentFives, paymentOnes); }Add the following
catchclause after thetrystatement code block:catch { }You'll finish developing the
catchclause once you've created and thrown the exceptions.
Create and throw exceptions in the MakeChange method
In this task, you'll update MakeChange to create and throw custom exceptions when a transaction can't be completed.
The MakeChange method includes two issues that should result in exceptions:
Underpayment issue: This issue occurs when the customer offers a payment that is less than the item cost. If the customer hasn't offered sufficient payment,
MakeChangeshould throw an exception.Insufficient till issue: This issue occurs when the till doesn't contain the bills required to produce the exact change. If the till can't make exact change,
MakeChangeshould throw and exception.
Scroll down to the
MakeChangemethod.Locate the following code lines:
if (changeNeeded < 0) transactionMessage = "Not enough money provided.";Take a minute to consider the issue that this code is addressing.
If
changeNeededis less than zero, the customer has not provided enough money to cover the purchase price of the item they're buying. The purchase price and the money provided by the customer are parameters of theMakeChangemethod. The method is unable to complete the transaction when the customer doesn't provide enough money. In other words, the operation fails.There are two exception types that appear to match these conditions:
InvalidOperationException: AnInvalidOperationExceptionexception should only be thrown when the operating conditions of a method don't support the successful completion of a particular method call. In this case the operating conditions are established by the parameters supplied to the method.ArgumentOutOfRangeException- AnArgumentOutOfRangeExceptionexception should only be thrown when the value of an argument is outside the allowable range of values as defined by the invoked method. In this case the money provided must be greater than the cost of the item.
Either exception type could work, but
InvalidOperationExceptionis a slightly better match in the context of this application.Update the code as follows:
if (changeNeeded < 0) throw new InvalidOperationException("InvalidOperationException: Not enough money provided to complete the transaction.");Scroll down to locate the following code lines:
if (changeNeeded > 0) transactionMessage = "Can't make change. Do you have anything smaller?";Take a minute to consider the issue that this code is addressing.
If
changeNeededis greater than zero after thewhileloops that prepare the change, then the till has run out of bills that can be used to make change. The method is unable to complete the transaction when the till lacks the bills required to make change. In other words, the operation fails.The
InvalidOperationExceptionexception should be used to create the exception.Update the code as follows:
if (changeNeeded > 0) throw new InvalidOperationException("InvalidOperationException: The till is unable to make the correct change.");
Complete the catch code block
In this task, you'll update the catch clause to catch a specific exception type.
Scroll up above the
MakeChangemethod, and locate the following code:catch { }To catch the exception type thrown in the
MakeChangemethod, update the code as follows:catch (InvalidOperationException e) { Console.WriteLine($"Could not complete transaction: {e.Message}"); }The
InvalidOperationExceptionexception object thrown inMakeChangewill be caught, but other exception types won't. Since you're not prepared to handle other exception types, it's important to let them be caught lower in the call stack. If you become aware that other exception types are expected withinMakeChange, you can add additionalcatchclauses.Use the File menu to save your updates.
Convert the MakeChange method from "string" to "void" and access exception properties
In this task, you'll update MakeChange to be of type void, and then use exception properties to communicate issue details to the user.
Scroll to the top of the
MakeChangemethod.To convert the
MakeChangemethod from typestringto typevoid, update the code as follows:static void MakeChange(int cost, int[] cashTill, int twenties, int tens = 0, int fives = 0, int ones = 0)Delete the following variable declaration:
string transactionMessage = "";Scroll to the bottom of the
MakeChangemethod.Delete the following code lines:
if (transactionMessage == "") transactionMessage = "transaction succeeded"; return transactionMessage;Scroll up to the top-level statements and locate the
trycode block.Update the
trycode block as follows:try { // MakeChange manages the transaction and updates the till MakeChange(itemCost, cashTill, paymentTwenties, paymentTens, paymentFives, paymentOnes); Console.WriteLine($"Transaction successfully completed."); registerCheckTillTotal += itemCost; }Locate and then delete the following code lines:
// Backup Calculation - each transaction adds current "itemCost" to the till if (transactionMessage == "transaction succeeded") { Console.WriteLine($"Transaction successfully completed."); registerCheckTillTotal += itemCost; } else { Console.WriteLine($"Transaction unsuccessful: {transactionMessage}"); }The
tryandcatchcode blocks are now communicating the transaction "success" and "failure" messages to the user. Since the exception'sMessageproperty describes the issue, a singleConsole.WriteLine()statement addresses both issues. Your code is easier to read and maintain after these updates.Use the File menu to save your updates.
Check your work
In this task, you'll run your application and verify that your updated code works as intended.
Scroll up to find the
whileloop in the top-level statements.This loop is used to iterate through the transactions.
Locate the following code a few lines before the start of the
whileloop.int transactions = 10;Update the number of transactions to
40as follows:int transactions = 40;Locate the following code line inside the
whileloop.int itemCost = valueGenerator.Next(2, 20);Update the
itemCostrandom number generator as follows:int itemCost = valueGenerator.Next(2, 50);This cost range is a better match for items that customers will be purchasing.
Use the File menu to save your updates.
On the Run menu, select Start Debugging.
Review the output in the TERMINAL panel.
Verify that the messages associated with the two exception types are displayed:
Your transactions report should include the following "Could not complete transaction" messages:
Customer is making a $42 purchase Using 2 twenty dollar bills Using 0 ten dollar bills Using 0 five dollar bills Using 0 one dollar bills Could not complete transaction: InvalidOperationException: Not enough money provided to complete the transaction.Customer is making a $23 purchase Using 2 twenty dollar bills Using 0 ten dollar bills Using 0 five dollar bills Using 1 one dollar bills Cashier prepares the following change: A five A five A one A one Could not complete transaction: InvalidOperationException: The till is unable to make change for the cash provided.
Congratulations, you've debugged the cash register application to fix a code logic issue, and you've updated the application to use proper exception handling techniques.
Note
The reported output shows that the money till is no longer balanced. There are additional logic bugs in the code. A challenge project module is available if you're interested in demonstrating your Visual Studio Code debugging skills!