【问题标题】:C# not entering exception after using throw使用 throw 后 C# 未进入异常
【发布时间】:2019-02-17 00:26:25
【问题描述】:

我是一名初级程序员,最近遇到了异常。我在下面做了这个小测试,我收到的输出与我预期的不一样。

static void Main(string[] args)
    {
        ushort var = 65535;
        try
        {
            checked { var++; }
        }
        catch (OverflowException)
        {
            Console.WriteLine("Hello!");
            throw;
        }
        catch
        {
            Console.WriteLine("Here I am!");

        }
    }

我希望程序执行以下操作:

  • 尝试 var++,失败并创建 OverflowException;
  • 输入 Catch (OverflowException) 并写“Hello!”;
  • 抛出异常并进入catch;
  • 写下“我在这里!”。

但是,我只看到屏幕“你好!”。

编辑:感谢那些发表评论的人。我想我开始明白了。然而,我的困惑源于我正在阅读的这本书:C# 4.0。

我可以显示文本,但它是葡萄牙语。我将翻译它所说的内容:“有时通过多个捕获传播异常是有用的。例如,假设有必要显示特定的错误消息,因为“idade”是无效的,但是我们仍然需要关闭程序,作为全局catch中的那一部分。在这种情况下,有必要在执行第一个catch块之后传播异常。为此,您只需执行一个简单的throw没有参数。”

Example from the book

在本书的这个例子中,你可以看到程序员做了我做的同样的事情。至少它看起来像。我错过了什么吗?还是书错了?

希望你能帮助我。谢谢!

【问题讨论】:

  • 当你的代码在一个方法中时你应该使用 throw,并且被调用的方法会处理你的 throw
  • 通过在 catch 块中写入 throw,您将重新抛出异常。它不会在下一个 catch 块中被捕获,但如果有的话,它会在外部 catch 块中被捕获。
  • 如果您想执行第二次捕获中的代码,无论异常是什么或没有异常,请尝试使用finally
  • 不会乱扔的,书上哪里这么说的?
  • "有时通过多个 catch 传播异常很有用" 这应该是"多个 try 块"。该部分的每个部分似乎都将 catch 与它的部分关闭的 try 块混淆了。应该是翻译错误。除了那个错误,顺便说一句,这是正确的。包括使用 'throw;',因为这是一种不会改变堆栈跟踪的重新抛出方法。

标签: c# exception try-catch throw


【解决方案1】:

简而言之,你做错了。让我们访问文档

Exception Handling (C# Programming Guide)

可以链接具有不同异常过滤器的多个 catch 块 一起。捕获块在您的 代码,但对于每个异常只执行一个 catch 块 被抛出

虽然它没有明确说您不能捕获已在异常过滤器中重新抛出的异常,但事实是您不能。这将是一场噩梦,并且会产生复杂和意想不到的结果。

就是说,您将需要try catch 的另一层(内部或外部)来捕获catch (OverflowException) 中引发的异常

【讨论】:

    【解决方案2】:

    如果嵌套try/catch 块,您将获得预期的输出:

    static void Main(string[] args)
    {
        try
        {
            ushort var = 65535;
            try
            {
                checked { var++; }
            }
            catch (OverflowException)
            {
                Console.WriteLine("Hello!");
                throw;
            }
        }
        catch
        {
            Console.WriteLine("Here I am!");
        }
    }
    

    【讨论】:

      【解决方案3】:

      我有两篇关于异常处理的文章,我经常链接。我个人认为在处理它们时需要阅读它们:

      https://blogs.msdn.microsoft.com/ericlippert/2008/09/10/vexing-exceptions/

      https://www.codeproject.com/Articles/9538/Exception-Handling-Best-Practices-in-NET

      对于这种情况,您并没有抛出异常。你正在重新投掷你抓住的一个。把它想象成一个渔夫在做“捕获和释放”。它可以用于某些场景,比如这次我为卡在 .NET 1.1 上的人写了一个 TryParse 替换:

      //Parse throws ArgumentNull, Format and Overflow Exceptions.
      //And they only have Exception as base class in common, but identical handling code (output = 0 and return false).
      
      bool TryParse(string input, out int output){
        try{
          output = int.Parse(input);
        }
        catch (Exception ex){
          if(ex is ArgumentNullException ||
            ex is FormatException ||
            ex is OverflowException){
            //these are the exceptions I am looking for. I will do my thing.
            output = 0;
            return false;
          }
          else{
            //Not the exceptions I expect. Best to just let them go on their way.
            throw;
          }
        }
      
        //I am pretty sure the Exception replaces the return value in exception case. 
        //So this one will only be returned without any Exceptions, expected or unexpected
        return true;
      
      }
      

      但根据经验,您应该使用“finally”块之类的东西进行清理工作,而不是捕获和释放。 throw 在 catch 块中是你很少使用的东西。

      【讨论】:

        猜你喜欢
        • 2015-01-09
        • 2016-04-24
        • 1970-01-01
        • 2012-05-18
        • 2020-10-29
        • 1970-01-01
        • 2018-03-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多