我已经养成了使用一般性catch语句并以一般方式处理这些异常的习惯。这是不好的实践吗?如果是,那么我怎么知道哪些特定的异常可能会被抛出,哪些异常需要被捕获?
我已经养成了使用一般性catch语句并以一般方式处理这些异常的习惯。这是不好的实践吗?如果是,那么我怎么知道哪些特定的异常可能会被抛出,哪些异常需要被捕获?
是的,除了一些非常特定的情况,这是个不好的做法。我知道的唯一一个普遍适用的情况是,在应用程序即将关闭之前记录消息或堆栈跟踪(或者可能是记录和重新抛出)。
仅捕获您知道可以处理的异常,不多不少。如果您不知道方法可能会引发哪些异常,那么您也不会正确处理它们,所以不要捕获。方法和库负责记录您应该能够处理的异常。此外,不要捕获指示逻辑失败的异常,例如 NullReferenceException
和 ArgumentException
。这些表明您的软件中存在真正的错误,应该修复,而不是在运行时处理。
EasyFooDocument
有一个构造函数,指定要加载的文件,并且它是从接收到来自“打开文件”对话框的文件名的代码中调用的。在加载过程中可能会出现无数问题,正确处理其中99.44%的方法是通知用户无法加载文件。即使程序员没有预料到特定的异常,很可能也应该以相同的方式处理它。 - supercatfinally
块有一个Exception
参数来指示在try
块中抛出了什么异常,如果有的话),那么情况可能会好得多。有很多情况下,方法抛出的异常将表明某个数据结构已经损坏,但并不清楚这是否是一个问题。如果数据结构是从无效的用户提供的文件构建的,则丢弃它将解决问题。然而,如果该结构对操作是必需的,... - supercat是的,那是一种不好的做法。原则是:“捕获你有能力响应的异常,让其他异常消失。”
try {
File.Open(usersChosenFile, FileMode.Open);
} catch(FileNotFoundException) {
// tell the user the file is gone, give them a chance to respond
// this is good
} catch(UnauthorizedAccessException) {
// this is good too
} catch(Exception) {
// what did you just catch? Who knows. What if its OutOfMemoryException?
// Do you really want to deal with that here? Let this one go by
}
您运行的方法通常会显示可能抛出的异常。然后您可以相应地捕获。
如果是您自己的代码,通常可以看到将会抛出什么异常,或者使用底层类的异常作为指南,以了解需要捕获哪些异常。
我推荐一些链接:
更重要的问题是,你是否需要对特定的异常进行特定的错误处理。如果你只需要捕获发生的任何错误,那么使用通用的try/catch块没有任何问题:
try
{
// Some Code
}
catch
{
}
然而,如果你需要对某些异常做特定处理,你可以在单个try块中指定多个catch块:
try
{
// Some Code
}
catch(ArgumentException argE)
{
}
catch(NullReferenceException nullE)
{
}
catch(Exception e)
{
// Everything else
}
在我看来 - 除非你打算为其增加价值和/或它只能在该方法中处理,否则不要捕获任何异常。
请确保有一个通用的异常处理程序来处理所有未处理的异常。
希望对你有所帮助。
catch(Exception e) {...}
中打印异常类型,则也可以通过经验发现异常。您需要的是e.GetType().FullName
、e.StackTrace
、e.Message
和e.InnerException
…或我列出的子集。文档通常描述一个方法可能抛出的异常以及可能发生的条件。这在微软.NET框架的参考文档中尤为突出。
在我看来,只有在有充分理由时才应该捕获异常。这通常意味着以通用方式捕获和处理它们是不必要的。记录异常(异常处理程序中非常常见的活动)应仅在调用堆栈底部或不重新抛出(可能包装的)异常时发生,这应该很少发生。如果您希望在异常向下冒泡时在调用堆栈中的每个帧上执行某些操作,请查看面向方面的编程(AOP)技术。
除非在罕见的情况下,我通常认为catch块是代码异味。
通过事先检查条件来防止抛出异常。例如,如果从文件中读取,请使用System.IO中的类检查文件是否存在,而不是使用catch块来处理文件不存在的情况。
catch块不应成为您的应用程序逻辑的一部分。
你应该捕获那些你可以开发合理策略来处理问题的异常。如果没有合理的替代方案(稍后再试、使用不同的技术/方法来实现相同的总体目标、告知用户当前无法实现目标以及他们可以采取什么措施来解决问题),那么捕获异常就没有意义。
异常(请原谅):值得在最高级别(例如Application.ThreadException或AppDOmain.UnhandledException)上拥有一些东西,以尝试记录那些你没有处理的异常。如果记录失败,你注定会失败。
但是盲目地吞噬所有异常(特别是在低层次)可能会导致非常令人沮丧的调试/诊断过程。