练习 - 在 C# 控制台应用程序中引发和捕获异常

已完成

在本练习中,在顶级语句中开发 try 代码块和 catch 子句,在 MakeChange 方法中创建并引发异常,然后使用异常对象完成 catch 代码块。 在本练习中,完成以下任务:

  1. 更新顶级语句:在顶级语句中实现 try-catch 模式。 try 代码块将包含对 MakeChange 的调用。
  2. 更新 MakeChange 方法:对“出纳机现金不足”和“付款不足”问题创建并引发异常。
  3. 更新 catch 代码块以使用引发的异常的属性。
  4. 验证测试:对在本练习中开发的代码执行验证测试。

向顶级语句添加 try-catch 模式

在此任务中,在 MakeChange 语句中包含对 try 方法的调用,并创建相应的 catch 子句。

  1. 在 Visual Studio Code 编辑器中,确保已打开 Program.cs 文件。

  2. 找到以下代码行:

    // 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}");
    }
    
  3. 花一点时间考虑此代码的用途。

    请注意,MakeChange 返回一个字符串值。 返回值会分配给名为 transactionMessage 的变量。 如果 transactionMessage 等于“交易成功”,则所购物品的成本将添加到 registerCheckTillTotal。 变量 registerCheckTillTotal 用于验证通过 MakeChange 方法计算的出纳机余额。

  4. 若要将对 MakeChange 方法的调用包含在 try 语句代码块中,请更新代码,如下所示:

    try
    {
        // MakeChange manages the transaction and updates the till 
        string transactionMessage = MakeChange(itemCost, cashTill, paymentTwenties, paymentTens, paymentFives, paymentOnes);
    }
    
  5. catch 语句代码块后,添加以下 try 子句:

    catch
    {
    }
    

    创建并引发异常后,便完成了 catch 子句的开发。

MakeChange 方法中创建并引发异常

在此任务中,更新 MakeChange 以在交易无法完成时创建和引发自定义异常。

MakeChange 方法包括两个应导致异常的问题:

  • “付款不足”问题:当客户提供的付款少于物品成本时,就会出现此问题。 如果客户未提供足够的付款,MakeChange 应引发异常。

  • “出纳机现金不足”问题:当出纳机中没有准确找零所需的纸币时,就会出现此问题。 如果出纳机不能准确找零,MakeChange 应引发异常。

  1. 向下滚动到 MakeChange 方法。

  2. 找到以下代码行:

    if (changeNeeded < 0)
        transactionMessage = "Not enough money provided.";
    
  3. 花一点时间考虑此代码要解决的问题。

    如果 changeNeeded 小于零,则客户没有提供足够的资金来支付其所购物品的购买价格。 购买价格和客户提供的资金是 MakeChange 方法的参数。 当客户未提供足够的资金时,该方法无法完成交易。 换句话说,操作失败。

    有两种异常类型似乎与以下条件匹配:

    • InvalidOperationException:只有当方法的操作条件不支持成功完成特定方法调用时,才应引发 InvalidOperationException 异常。 在这种情况下,操作条件由提供给该方法的参数确定。
    • ArgumentOutOfRangeException - 只有当自变量的值超出了所调用方法定义的允许值范围时,才应引发 ArgumentOutOfRangeException 异常。 在这种情况下,提供的资金必须大于物品的成本。

    任一异常类型都可工作,但 InvalidOperationException 在此应用程序的上下文中稍微更合适一些。

  4. 按如下所示更新代码:

    if (changeNeeded < 0)
        throw new InvalidOperationException("InvalidOperationException: Not enough money provided to complete the transaction.");
    
  5. 向下滚动以找到以下代码行:

    if (changeNeeded > 0)
        transactionMessage = "Can't make change. Do you have anything smaller?";
    
  6. 花一点时间考虑此代码要解决的问题。

    如果 changeNeeded 在准备找零的 while 循环后大于零,则出纳机中可用于找零的纸币已经用完。 当出纳机缺少找零所需的纸币时,该方法不能完成交易。 换句话说,操作失败。

    应使用 InvalidOperationException 异常来创建异常。

  7. 按如下所示更新代码:

    if (changeNeeded > 0)
        throw new InvalidOperationException("InvalidOperationException: The till is unable to make the correct change.");
    

完成 catch 代码块

在此任务中,更新 catch 子句以捕获特定的异常类型。

  1. 向上滚动到 MakeChange 方法上方,找到以下代码:

    catch
    {
    }    
    
  2. 若要捕获 MakeChange 方法中引发的异常类型,请更新代码,如下所示:

    catch (InvalidOperationException e)
    {
        Console.WriteLine($"Could not complete transaction: {e.Message}");
    }    
    

    将捕获 InvalidOperationException 中引发的 MakeChange 异常对象,但不会捕获其他异常类型。 由于你尚未准备好处理其他异常类型,因此请务必使它们在调用堆栈中较低位置被捕获。 如果发现 MakeChange 中预期有其他异常类型,可添加其他 catch 子句。

  3. 使用“文件”菜单保存更新。

将 MakeChange 方法从“string”转换为“void”并访问异常属性

在此任务中,将 MakeChange 更新为 void 类型,然后使用异常属性向用户传达问题详细信息。

  1. 滚动到 MakeChange 方法的顶部。

  2. 若要将 MakeChange 方法从 string 类型转换为 void 类型,请更新代码,如下所示:

    static void MakeChange(int cost, int[] cashTill, int twenties, int tens = 0, int fives = 0, int ones = 0)
    
  3. 删除以下变量声明:

    string transactionMessage = "";
    
  4. 滚动到 MakeChange 方法的底部。

  5. 删除以下代码行:

    if (transactionMessage == "")
        transactionMessage = "transaction succeeded";
    
    return transactionMessage;
    
  6. 向上滚动到顶级语句并找到 try 代码块。

  7. 按如下所示更新 try 代码块:

    try
    {
        // MakeChange manages the transaction and updates the till 
        MakeChange(itemCost, cashTill, paymentTwenties, paymentTens, paymentFives, paymentOnes);
    
        Console.WriteLine($"Transaction successfully completed.");
        registerCheckTillTotal += itemCost;
    }
    
  8. 找到并删除以下代码行:

    // 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}");
    }
    
    

    trycatch 代码块现在向用户传达交易“成功”和“失败”消息。 由于异常的 Message 属性描述了该问题,因此一条 Console.WriteLine() 语句可同时解决这两个问题。 经过这些更新后,代码更易于阅读和维护。

  9. 使用“文件”菜单保存更新。

检查你的工作

在此任务中,运行应用程序并验证更新的代码按预期工作。

  1. 向上滚动以在顶级语句中查找 while 循环。

    此循环用于循环访问交易。

  2. while 循环开始前几行,找到以下代码。

    int transactions = 10;
    
    
  3. 将交易数更新为 40,如下所示:

    int transactions = 40;
    
    
  4. while 循环中找到以下代码行。

    int itemCost = valueGenerator.Next(2, 20);
    
    
  5. 按如下所示更新 itemCost 随机数生成器:

    int itemCost = valueGenerator.Next(2, 50);
    
    

    此成本范围更适合客户将购买的物品。

  6. 使用“文件”菜单保存更新。

  7. 在“运行”菜单上,选择“开始调试”。

  8. 在“终端”面板中查看输出。

  9. 验证显示了与两种异常类型关联的消息:

    交易报告应包含以下“无法完成交易”消息:

    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.
    
    

恭喜,你已调试现金出纳机应用程序以修复代码逻辑问题,并且已更新应用程序以使用适当的异常处理技术。

注意

报告的输出显示,现金出纳机余额不足。 代码中还存在其他逻辑 bug。 如果有兴趣演示 Visual Studio Code 调试技能,可以使用挑战项目模块!