3

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

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

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

我读到,当您throw出现异常时,无需添加break;语句,因为 switch 语句在遇到throw关键字时会中断,但我不确定这是否是本示例中的正确思维方式。

请帮助我理解第throw70 行关键字的含义。

先感谢您。

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;
         }
      }
   }
}

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

4

4 回答 4

3

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

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

于 2013-10-07T13:24:05.603 回答
3

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

于 2013-10-07T13:25:13.750 回答
1

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

查看Rethrow 以保留堆栈详细信息

同样来自try-catch(C# 参考)

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

catch
{
    throw;
}
于 2013-10-07T13:23:56.810 回答
1

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

请看这个:关于重新抛出异常的问题 和这个:codinghorror blogpost(请注意评论中的澄清)

于 2013-10-07T13:28:11.440 回答