23

我正在用 C# 编写一个自定义类,如果人们在某些方法中输入错误,我会抛出几个异常。如果抛出异常,抛出后方法中的任何代码是否仍会被执行?我必须在投掷后休息一下,还是投掷总是退出该方法?

4

6 回答 6

36

当您抛出异常时,下一个要执行的代码是在方法中覆盖该抛出的任何 catch 块(如果有),然后是finally 块(如果有)。你可以尝试一下,try-catch,try-catch-finally 或 try-finally。然后,如果异常未被处理、被 catch 块重新抛出或根本没有被捕获,则将控制权返回给调用者。例如,您将从这段代码中得到“Yes1, Yes2, Yes3”...

try
{
    Console.WriteLine("Yes1");
    throw (new Exception());
    Console.WriteLine("No1");

}
catch
{
    Console.WriteLine("Yes2");
    throw;
    Console.WriteLine("No2");
}
finally
{
    Console.WriteLine("Yes3");
}

Console.WriteLine("No3");
于 2009-06-13T06:27:53.883 回答
27

Throw 将向上移动堆栈,从而退出该方法。

于 2009-06-13T06:22:07.763 回答
4

我建议使用调试器单步执行您的程序,然后您将亲眼看到发生了什么。对学习非常有用!

于 2009-06-13T14:12:08.320 回答
2

我来这里是为了寻找原始帖子的答案,但几乎错过了Eric Lippert发布的一个非常有价值的答案。这是他在评论中发布的答案:

把它分成三个问题。

(1) throw 后方法中的任何代码都会被执行吗?
是的。如果异常在 try 中,则匹配的 catch 块或 finally 块中的代码将被执行。如果没有尝试块,则否。控制分支到最近的封闭最终,捕获或(在 vb 中)异常过滤器阻塞堆栈。

(2) 我必须在投掷后休息吗?
不,永远不要那样做。throw语句的终点不可达;编译器将 throw 视为 goto。紧跟在 throw 之后的语句是不可访问的,并且永远不会执行。

(3) throw 总是退出方法吗?
不。如果 throw 在 try 中并且 try 具有匹配的 catch 块,则 catch 块可以“吃掉”异常。只有在没有 catch 块的情况下,异常才会在调用堆栈上执行非本地 goto。

如果您对此有更多疑问,我建议您阅读 C# 规范;所有这些行为都有明确的记录。

最后,听起来你正在抛出“愚蠢的”异常,就像“嘿,愚蠢的调用者,我告诉你永远不要给我那个数据”一样。这很棒,因为它可以防止调用者出现错误。但是如果你这样做,你应该确保调用者有某种方式知道你的期望!如果调用者无法根据您的文档确定您是否要抛出,那么您还没有做出愚蠢的异常,您已经做出了令人烦恼的异常。有关详细信息,请参阅http://blogs.msdn.com/ericlippert/archive/2008/09/10/vexing-exceptions.aspx

于 2017-03-23T18:06:59.537 回答
1

如果您已将代码包装在 Try...Catch...Finally 块中,则 finally 下的代码将始终执行。例如:

Try
  ' do some stuff here
  ' Examine user input
  If user input isn't valid
      Throw new exception
Catch
   Throw ' Just re-throws the same exception
Finally
   ' This code will execute, no matter what - exception or not
End Try
于 2009-06-13T06:29:39.620 回答
1

除了您的实际问题:您可能需要重新考虑使用异常来向用户提供验证信息。

引发异常在资源方面是昂贵且缓慢的。如果您有许多需要应用的验证规则,请为这些规则编写特定的代码——您可能应该只依赖异常处理来处理您没有预料到的事情。

于 2009-06-13T11:07:10.280 回答