【问题标题】:What is the throw keyword responsible for in a C# error handling exercise在 C# 错误处理练习中,throw 关键字负责什么
【发布时间】:2013-10-14 02:18:40
【问题描述】:

我正在尝试学习如何使用 VS2012 for Desktop 调试和处理 C# 代码中的错误。我正在使用 Step Into F11 技术逐步执行以下代码。

我了解代码的执行如何在代码的不同部分之间跳转。我将消息打印到控制台以帮助我确定正在执行的步骤。我已经拆分了我的屏幕,这样我就可以同时看到我正在进入哪一行代码以及控制台中的输出消息。

在第 70 行(在 cmets 中标记) - 当 nested index 传递给 throwException() 时,我不明白为什么会有 throw 关键字以及它的功能是什么。为什么指针会跳转到嵌套的 finally 块,然后它会一直返回到 main 并抛出 IndexOutOfBounds 异常。那是什么意思?我看到代码中执行跳转的位置,但我不明白为什么它只是说throw。这是否意味着已经处理了异常?但是怎么做呢?

我读到当你 throw 出现异常时,不需要添加 break; 语句,因为 switch 语句在遇到 throw 关键字时会中断,但我不确定这是正确的思考方式这个例子。

请帮我理解第 70 行的 throw 关键字的含义。

提前谢谢你。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Ch07Ex02
{
   class Program
   {
      static string[] eTypes = { "none", "simple", "index", "nested index" };

      static void Main(string[] args)
      {
         foreach (string eType in eTypes)
         {
            try
            {
               Console.WriteLine("Main() try block reached.");        // Line 19
               Console.WriteLine("ThrowException(\"{0}\") called.", eType);
               ThrowException(eType);
               Console.WriteLine("Main() try block continues.");      // Line 22
            }
            catch (System.IndexOutOfRangeException e)                 // Line 24
            {
               Console.WriteLine("Main() System.IndexOutOfRangeException catch"
                                 + " block reached. Message:\n\"{0}\"",
                                 e.Message);
            }
            catch                                                     // Line 30
            {
               Console.WriteLine("Main() general catch block reached.");
            }
            finally
            {
               Console.WriteLine("Main() finally block reached.");
            }
            Console.WriteLine();
         }
         Console.ReadKey();
      }

      static void ThrowException(string exceptionType)
      {
         Console.WriteLine("ThrowException(\"{0}\") reached.", exceptionType);
         switch (exceptionType)
         {
            case "none":
               Console.WriteLine("Not throwing an exception.");
               break;                                               // Line 50
            case "simple":
               Console.WriteLine("Throwing System.Exception.");
               throw new System.Exception();                        // Line 53
            case "index":
               Console.WriteLine("Throwing System.IndexOutOfRangeException.");
               eTypes[4] = "error";                                 // Line 56
               break;
            case "nested index":
               try                                                  // Line 59
               {
                  Console.WriteLine("ThrowException(\"nested index\") " +
                                    "try block reached.");
                  Console.WriteLine("ThrowException(\"index\") called.");
                  ThrowException("index");                          // Line 64
               }
               catch                                                // Line 66
               {
                  Console.WriteLine("ThrowException(\"nested index\") general"
                                    + " catch block reached.");
                  throw;                                            // Line 70 
               }
               finally
               {
                  Console.WriteLine("ThrowException(\"nested index\") finally"
                                    + " block reached.");
               }
               break;
         }
      }
   }
}

上面的代码编译运行没有错误。

【问题讨论】:

  • 所有答案都很好,也很有意义,所以谢谢大家。我只能接受一个答案,以弥补我对所有答案的投票。

标签: c# exception-handling error-handling try-catch throw


【解决方案1】:

throw 关键字用于重新抛出捕获的异常,而不会丢失正确的堆栈跟踪。它用于在捕获异常时执行某些操作(例如日志记录,就像在您的示例中一样)。

请看这个:SO qeustion on rethrowing exceptions 还有这个:codinghorror blogpost(请注意 cmets 中的说明)

【讨论】:

    【解决方案2】:

    throw; 在 catch 中表示“我实际上不知道如何处理这个异常,所以让堆栈中更高的其他人捕获它(我没有修改它)。”

    【讨论】:

      【解决方案3】:

      关键字throw 可以在catch 子句中单独使用,以重新抛出该catch 块捕获的任何异常。它允许您在处理异常的过程中“插入”一些执行逻辑,而不会破坏引发异常的详细信息。

      在这种情况下,您可以将详细信息记录到控制台,然后重新抛出异常,就好像您从未处理过它一样。请注意,这与捕获异常并将其包装在您自己的异常中不同,因为原始异常的详细信息被保留了。

      【讨论】:

      • 这是否意味着捕获的异常被重新抛出(passed)到 Main() 块? IE。 异常被捕获,但让更高层次的代码处理它
      • @mehow 正确,捕获的异常被重新抛出到任何外部块来处理它 - 在你的情况下,这就是你的 Main 方法的 catch 块。
      • @mehow,是的,在执行 finally 块之后。
      【解决方案4】:

      有问题的 throw 将重新抛出异常,从而保留堆栈跟踪和其他信息。

      看看Rethrow to preserve stack details

      同样来自try-catch (C# Reference)

      如果你想重新抛出当前由 a 处理的异常 无参数的 catch 子句,使用不带参数的 throw 语句

      catch
      {
          throw;
      }
      

      【讨论】:

        猜你喜欢
        • 2023-01-14
        • 1970-01-01
        • 2014-07-12
        • 2015-12-23
        • 1970-01-01
        • 2010-12-08
        • 2012-05-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多