我正在用 C# 编写一个自定义类,如果人们在某些方法中输入错误,我会抛出几个异常。如果抛出异常,抛出后方法中的任何代码是否仍会被执行?我必须在投掷后休息一下,还是投掷总是退出该方法?
6 回答
当您抛出异常时,下一个要执行的代码是在方法中覆盖该抛出的任何 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");
Throw 将向上移动堆栈,从而退出该方法。
我建议使用调试器单步执行您的程序,然后您将亲眼看到发生了什么。对学习非常有用!
我来这里是为了寻找原始帖子的答案,但几乎错过了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。
如果您已将代码包装在 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
除了您的实际问题:您可能需要重新考虑使用异常来向用户提供验证信息。
引发异常在资源方面是昂贵且缓慢的。如果您有许多需要应用的验证规则,请为这些规则编写特定的代码——您可能应该只依赖异常处理来处理您没有预料到的事情。