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-catch
pattern in the top-level statements. Thetry
code block will contain the call toMakeChange
. - Update
MakeChange
method: Create and throw exceptions for "Insufficient till" and "Underpayment" issues. - Update the
catch
code 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
MakeChange
returns a string value. The return value is assigned to a variable namedtransactionMessage
. IftransactionMessage
is equal to "transaction succeeded", then the cost of the purchased item is added toregisterCheckTillTotal
. The variableregisterCheckTillTotal
is used to verify the till balance calculated by theMakeChange
method.To enclose the call to the
MakeChange
method in atry
statement 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
catch
clause after thetry
statement code block:catch { }
You'll finish developing the
catch
clause 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,
MakeChange
should 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,
MakeChange
should throw and exception.
Scroll down to the
MakeChange
method.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
changeNeeded
is 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 theMakeChange
method. 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
: AnInvalidOperationException
exception 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
- AnArgumentOutOfRangeException
exception 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
InvalidOperationException
is 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
changeNeeded
is greater than zero after thewhile
loops 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
InvalidOperationException
exception 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
MakeChange
method, and locate the following code:catch { }
To catch the exception type thrown in the
MakeChange
method, update the code as follows:catch (InvalidOperationException e) { Console.WriteLine($"Could not complete transaction: {e.Message}"); }
The
InvalidOperationException
exception object thrown inMakeChange
will 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 additionalcatch
clauses.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
MakeChange
method.To convert the
MakeChange
method from typestring
to 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
MakeChange
method.Delete the following code lines:
if (transactionMessage == "") transactionMessage = "transaction succeeded"; return transactionMessage;
Scroll up to the top-level statements and locate the
try
code block.Update the
try
code 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
try
andcatch
code blocks are now communicating the transaction "success" and "failure" messages to the user. Since the exception'sMessage
property 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
while
loop 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
while
loop.int transactions = 10;
Update the number of transactions to
40
as follows:int transactions = 40;
Locate the following code line inside the
while
loop.int itemCost = valueGenerator.Next(2, 20);
Update the
itemCost
random 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 make 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 make 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 make 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!