据我所知,你应该只在实际处理异常时才使用try / catch,而不仅仅是报告和记录它然后使应用程序崩溃。否则,最好只检查有意义的不同场景(例如,如果sth == null),或者 - 如果您的目的只是记录异常并使应用程序崩溃 - 使用AppDomain.UnhandledException。但情况总是这样吗?为什么?
假设以下方法接受一个数组并在执行一些数据库和文件系统操作后返回MemoryStream。
MemoryStream Read (int[] IDs)
{
try
{
using (SqlConnection connection = new SqlConnection(connection_string))
{
connection.Open();
// a bunch of code executing SQL queries & constructing MemoryStream, which is returned at the end of the block
}
}
catch (Exception e)
{
// report the exception to the user & log it
throw; // pointles??
}
}
有多种情况可以被视为特殊/不受欢迎的行为,例如:
所有这些情况都被认为是例外情况,如果您只想记录异常(然后崩溃)可能是不好的做法,仍然将所有内容放在try / catch中 - 但为什么呢?在上述情况下,最佳处理行为是什么?完全避免try / catch,使用if语句检查空引用(在这种情况下返回null)并使用AppDomain.UnhandledException记录其他所有内容?使用try / catch,但仍然使用if语句检查空引用(在这种情况下返回)?还有别的吗?
答案 0 :(得分:2)
仅使用try / catch语句来编写代码以使应用程序崩溃是没有效率的。 CLR已经为您解决了这个问题。而且你有AppDomain.UnhandledException来生成正确的信息来诊断原因。
只有在您 清理某些内容的非常具体的情况下,如果您考虑编写try / catch,请说一个您不想继续放置的文件。这本身就是一个非常不确定的要求,不能保证你的catch块会执行。当异常像StackOverflowException或ExecutionEngineException一样令人讨厌时,它不会。或者更常见的原因是程序没有自行清理,有人绊倒电源线或从任务管理器中删除进程。
答案 1 :(得分:1)
你应该只在实际处理异常时才使用try / catch而不仅仅是报告&记录它然后崩溃应用程序
我同意第一部分,但我想补充一点,当你可能无法控制调用层时,在层边界添加日志记录是很有价值的。例如我在顶部方法中记录Web服务中发生的所有异常,以确保我已登录服务器,因为调试信息(堆栈跟踪等)并不总是优雅地跨通信层
在您的特定示例中,我会检查"例外"条件你可以,但让其他例外发生"自然"。对于您的具体示例:
- 参数(IDs [])为null,
- 无法建立SQL连接,
- 无法执行特定的SQL查询。
对于第一个,我会检查null
个参数的原因有一个:NullReferenceException
为您提供 no 关于异常原因的上下文,其他发生的地方。我更喜欢检查null
,然后抛出一个新的ArgumentNullException
异常,因为你可以添加哪个参数为null。您可能仍需要进行一些挖掘以找出为什么它为null,但它可以节省您大量的调试时间。
SQL异常通常会自然冒出来,因为它们中包含了不错的错误信息(例如"undeclared variable '@arg'"
)
答案 2 :(得分:1)
我最近开始自己阅读这个主题。我的基本理解是:
重要的是要注意“处理”异常并不一定意味着清理或追溯逻辑。处理可能只是意味着将错误格式化为更加用户友好的内容,或者隐藏您不希望任何人看到的敏感堆栈跟踪。我经常记录一个详细的错误并返回一个格式化的错误。
同样,这正是我最初收集的内容。以下是一些消息来源: